Issue with FunctionImport in Entity Framework 4

entity entity-framework

Question

Entity Framework 4 is what I use.

I have a stored procedure that only modifies the application state ID, which is one of the values in my database. So I developed a stored process that appears as follows:

ALTER PROCEDURE [dbo].[UpdateApplicationState]
(
   @ApplicationID INT,
   @ApplicationStateID INT
)

AS

BEGIN

   UPDATE
      [Application]
   SET
      ApplicationStateID = @ApplicationStateID
   WHERE
      ApplicationID = @ApplicationID;

END

UpdateApplicationState is the name of a function I developed. It wasn't formed in the context when I first set its return type to null. I therefore modified the return type to int. It was now produced inside the situation. Is returning anything from my stored procedure a good idea?

In my ApplicationRepository class, I have the following method:

public void UpdateApplicationState(int applicationID, int applicationStateID)
{
   var result = context.UpdateApplicationState(applicationID, applicationStateID);
}

Here is how I would name this strategy, in my opinion:

applicationRepository.UpdateApplicationState(id, newApplicationStateID);

I then get the below problem when I execute it:

The data reader returned by the store data provider does not have enough columns for the query requested.

Any suggestions as to how I may go about making this work?

Thanks

1
9
10/1/2010 8:39:54 AM

Accepted Answer

It's because your saved process doesn't truly return anything. If you add the following line to your SP (Choose @@ROWCOUNT), it will run correctly.

BEGIN    
    ...

    SELECT @@ROWCOUNT
END

Although this method will solve your problem and does in fact provide the number of rows affected by your SP, I'm not sure why this is a problem for you:

I had initially set its return type to null, but then it wasn't created in the context.

You may choose the return type "None" when doing a function import, and it will create a new method on your ObjectContext with the return type int. In essence, this method runs a stored procedure specified in the data source, discards any results produced by the function, and then provides the number of rows that were impacted by the execution.

EDIT: Reasons a function without a return value in a POCO scenario is disregarded:

Investigating the Template ObjectContext T4 file that is included with POCO Entity Generator in ADO.NET C# exposes the reason why your Function is hidden in the ObjectContext class: It is just disregarded! They leave the foreach loop, which creates the functions, and go to the next iteration.

The answer is to modify the T4 template such that it generates a method for functions that have no return type or merely return anything based on the first approach.

region.Begin("Function Imports");

foreach (EdmFunction edmFunction in container.FunctionImports)
{
    var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
    string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());

    // Here is why a Function without return value is ignored:
    if (edmFunction.ReturnParameter == null)
    {
        continue;
    }
    string returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage));
    ...
16
10/2/2010 2:37:20 PM

Popular Answer

You may edit the.Context.tt file in a manner similar to this to make POCO compatible with function imports that return null.

Locate the section called "Function Imports" that begins with the name "region." Region follows begin("Function Imports"); Replace the whole section (End();) in the.Context.tt file with the following:

    region.Begin("Function Imports");

        foreach (EdmFunction edmFunction in container.FunctionImports)
        {
            var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
            string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
            var isReturnTypeVoid = edmFunction.ReturnParameter == null;
            string returnTypeElement = String.Empty;
            if (!isReturnTypeVoid) 
                returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage));

#>
<# if (isReturnTypeVoid) { #>
    <#=Accessibility.ForMethod(edmFunction)#> void <#=code.Escape(edmFunction)#>(<#=paramList#>)    
<# } else { #>
    <#=Accessibility.ForMethod(edmFunction)#> ObjectResult<<#=returnTypeElement#>> <#=code.Escape(edmFunction)#>(<#=paramList#>)    
<# } #>
    {
<#
            foreach (var parameter in parameters)
            {
                if (!parameter.NeedsLocalVariable)
                {
                    continue;
                }
#>

        ObjectParameter <#=parameter.LocalVariableName#>;

        if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>)
        {
            <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>);
        }
        else
        {
            <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>));
        }
<#
            }
#>
<# if (isReturnTypeVoid) { #>
        base.ExecuteFunction("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
<# } else { #>
        return base.ExecuteFunction<<#=returnTypeElement#>>("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
<# } #>

    }
<#
        }

        region.End();

Here, I'm constructing a method that returns null rather than disregarding any function imports that do so. Hopefully, this was useful.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow