实体框架 - 表值函数 - 参数已存在

时间:2013-10-07 16:51:51

标签: entity-framework entity-framework-5 parameter-passing user-defined-functions

我正在使用带有Entity Framework 5的表值函数。我刚收到此错误:

  

参数集合中已存在名为“EffectiveDate”的参数。参数名称在参数集合中必须是唯一的。参数名称:参数

这是因为我加入了对具有相同参数的表值函数的调用。

这是EF的错误/限制吗?有解决方法吗?现在我正在自动生成代码(.edmx文件)。

2 个答案:

答案 0 :(得分:11)

如果微软能够使参数名称唯一,那将是非常好的,至少在每个上下文的基础上。

我为此here创建了一个问题。

与此同时,我通过调整.Context.tt文件中的一些函数来实现这一点,以便在运行时向每个参数名称添加一个GUID:

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())));
}

答案 1 :(得分:1)

不是错误。也许是限制或遗漏。显然这个用例从未被考虑过。 EF 可以使用自动创建的参数名称,但是,是的,它不会。

您必须使用.AsEnumerable()来调用其中一个函数。出于某种原因,这必须是连接中的第一个功能(正如我所经历的那样)。如果使用.AsEnumerable()调用第二个函数,它仍然会转换为SQL并且仍然会发生名称冲突。