Entity Framework - Table Functions - Parameter Already Exists

I am using table functions with Entity Framework 5. I just got this error:

A parameter named "Performance" already exists in the parameter collection. Parameter names must be unique in the parameter collection. Parameter Name: Parameter

This is because I am connecting calls to table functions that take the same parameter.

Is this an error / limitation with EF? Is there a workaround? Right now I am automatically generating code (.edmx file).

+6
source share
2 answers

It would be nice if Microsoft made parameter names unique, at least based on context.

I created a problem for this here .

In the meantime, I was able to get this to work by editing several functions in the .Context.tt file so that it adds a GUID to each parameter name at runtime:

private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) { if (typeMapper.IsComposable(edmFunction)) { #> [EdmFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")] <#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#> { var guid = Guid.NewGuid().ToString("N"); <#+ codeStringGenerator.WriteFunctionParameters(edmFunction, " + guid", WriteFunctionParameter); #> <#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#> } <#+ } else { #> <#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#> { <#+ codeStringGenerator.WriteFunctionParameters(edmFunction, "", WriteFunctionParameter); #> <#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#> } <#+ if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption)) { WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true); } } } 

...

 public void WriteFunctionParameters(EdmFunction edmFunction, string nameSuffix, Action<string, string, string, string> writeParameter) { var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable)) { var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"; var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\"" + nameSuffix + ", " + parameter.FunctionParameterName + ")"; var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\"" + nameSuffix + ", typeof(" + parameter.RawClrTypeName + "))"; writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit); } } 

...

 public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace) { var parameters = _typeMapper.GetParameters(edmFunction); return string.Format( CultureInfo.InvariantCulture, "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});", _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), edmFunction.NamespaceName, edmFunction.Name, string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName + "\" + guid + \"").ToArray()), _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))); } 
+9
source

Not a mistake. Maybe a limitation or an omission. Apparently, this precedent has never been taken into account. EF can use automatically generated parameter names, but, yes, it just isn't.

You need to resort to calling one of the functions with .AsEnumerable() . For some reason, this should be the first function in the connection (as I said). If you call the second function using .AsEnumerable() , it still translates to SQL and a name clash occurs.

0
source

Source: https://habr.com/ru/post/955428/


All Articles