EF6中仍然支持模型定义的功能吗?

时间:2015-04-08 00:43:37

标签: entity-framework ado.net ado.net-entity-data-model

模型定义的函数在这里讨论:

是否支持EF6.1.2?

我踩过Edm / DbModel的东西,我不能在我的生活中解决< Function>的问题。 csdl中的元素应该被解析,因为它没有进入EdmModel(EdmModel.AddItem(EdmFunction)没有被调用)

ExpressionConverter.FindFunction在EdmModel._functions中查找,而_functions仅由EdmModel.AddItem(EdmFunction)添加,并且只能由扩展方法EdmModelExtensions.AddFunction()调用,而我无法在调用该函数的EntityFramework源代码。我一定错过了一些简单的事情......

更多:我放弃了在edmx中定义函数,现在我以编程方式创建我的EdmFunction并将其添加到自定义IConceptualModelConvention.Apply()方法中:

    class CustomFunctionConvention : IConceptualModelConvention<EdmModel>
    {
        public void Apply(EdmModel item, DbModel model)
        {
            var functionPayload = new EdmFunctionPayload () {
                CommandText = "CAST (strValue AS int)",
                Parameters = new [] {
                    FunctionParameter.Create("strValue", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String).GetEdmPrimitiveType(), ParameterMode.In),
                },
                ReturnParameters = new [] {
                    FunctionParameter.Create("ReturnValue", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32).GetEdmPrimitiveType(), ParameterMode.ReturnValue),
                },
                IsComposable = true,
            };

            var function = EdmFunction.Create("ParseInt", "MyNamespace", DataSpace.CSpace, functionPayload, null);
            model.ConceptualModel.AddItem(function);
        }
    }

但是现在我在EdmItemCollection.LoadItems()中收到了一堆架构错误:

Schema specified is not valid. Errors:
(0,0) : error 0005: The 'Aggregate' attribute is not allowed.
(0,0) : error 0005: The 'BuiltIn' attribute is not allowed.
(0,0) : error 0005: The 'NiladicFunction' attribute is not allowed.
(0,0) : error 0005: The 'IsComposable' attribute is not allowed.
(0,0) : error 0005: The 'ParameterTypeSemantics' attribute is not allowed.
(0,0) : error 0005: The 'Schema' attribute is not allowed.
(0,0) : error 0005: The 'Mode' attribute is not allowed.

1 个答案:

答案 0 :(得分:2)

看来,模型定义的函数首先可以使用代码。以下是ParseInt示例的版本:

namespace EfTestModelFunctions
{
    public class CustomFunctionConvention : IConceptualModelConvention<EdmModel>
    {
        public void Apply(EdmModel item, DbModel model)
        {
            var functionParseInt = new EdmFunctionPayload()
            {
                CommandText = String.Format("CAST(strValue AS {0})", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)),
                Parameters = new[] {
                    FunctionParameter.Create("strValue", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), ParameterMode.In),
                },

                ReturnParameters = new[] {
                    FunctionParameter.Create("ReturnValue", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.ReturnValue),
                },
                IsComposable = true
            };

            var function = EdmFunction.Create("ParseInt", model.ConceptualModel.EntityTypes.First().NamespaceName, DataSpace.CSpace, functionParseInt, null);
            model.ConceptualModel.AddItem(function);
        }
    }

    public class RootDataContext : DbContext
    {
        public RootDataContext()
            : base("Data Source=******")
        {
            Database.SetInitializer(new NullDatabaseInitializer<RootDataContext>());
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Add<CustomFunctionConvention>();
        }

        public DbSet<RootEntity> Roots { get; set; }

        // declare the function with the Context's NameSpace
        [DbFunction("EfTestModelFunctions", "ParseInt")]
        public static int ParseInt(string value)
        {
            throw new NotImplementedException();
        }
    }
}

用法将是:

var query = ctx.Roots.Where(r => RootDataContext.ParseInt(r.StringProperty)==123);

此外,涉及数据库迁移/初始化时似乎存在问题。看到 UpForGrabs: Unblock creation of model defined functions in model conventions