Entity Framework 6 Code First 函数映射 [英] Entity Framework 6 Code First function mapping

查看:15
本文介绍了Entity Framework 6 Code First 函数映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 Entity Framework 6 集成到我们的系统中,但是遇到了问题.

I want integrate Entity Framework 6 to our system, but have problem.

  1. 我想使用 Code First.由于其他原因,我不想使用 Database First *.edmx 文件.
  2. 我使用属性映射 [Table]、[Column] 并且效果很好
  3. 数据库有许多用户定义的函数,我需要在 Linq To Entities 查询中使用它们.

问题是:

我无法通过 [Table]、[Column] 等属性映射函数.只有 1 个属性可用 [DbFunction],需要 *.edmx 文件.

I cannot map function via attribute like [Table], [Column]. Only 1 attribute is available [DbFunction], which requires *.edmx file.

我可以在 *.edmx 文件中进行函数映射,但这意味着我不能对实体使用属性映射:[表]、[列].*.edmx 或属性中的映射必须是完整的.

I’m ok to have functions mapping in *.edmx file, but it means I cannot use attributes mapping for Entities: [Table], [Column]. Mapping must be full in *.edmx or in attributes.

我尝试通过此代码创建 DbModel 并添加功能:

I tried to create DbModel and add function via this code:

public static class Functions
{
    [DbFunction("CodeFirstNamespace", "TestEntity")]
    public static string TestEntity()
    {
        throw new NotSupportedException();
    }
}


public class MyContext : DbContext, IDataAccess
{
    protected MyContext (string connectionString)
        : base(connectionString, CreateModel())
    {
    }

    private static DbCompiledModel CreateModel()
    {
        var dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest);
        dbModelBuilder.Entity<Warehouse>();
        var dbModel = dbModelBuilder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));

        var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String);
        var payload =
            new EdmFunctionPayload
            {
                Schema = "dbo",
                ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                IsComposable = true,
                IsNiladic = false,
                IsBuiltIn = false,
                IsAggregate = false,
                IsFromProviderManifest = true,
                StoreFunctionName = "TestEntity",
                ReturnParameters =
                    new[]
                    {
                        FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
                    }
            };

        var function = EdmFunction.Create("TestEntity", "CodeFirst", DataSpace.CSpace, payload, null);
        dbModel.DatabaseMapping.Model.AddItem(function);
        var compiledModel = dbModel.Compile();       // Error happens here
        return compiledModel;
    }
}

但有例外:

在模型生成过程中检测到一个或多个验证错误:

One or more validation errors were detected during model generation:

Edm.String: : The namespace 'String' is a system namespace and cannot be used by other schemas. Choose another namespace name.

问题出在edmType"变量中.我无法为函数正确创建 ReturnType.有人可以建议我如何将功能添加到模型中吗?添加功能的接口是暴露的,所以应该可以做,但是网上没有关于这种情况的信息.可能有人知道 Entity Framework 团队何时会为 Line To Sql 之类的函数实现属性映射.

Problem is in "edmType" variable. I cannot create correctly ReturnType for function. Can anybody suggest how I can add function into model? Interface of adding function is exposed, so it should be able to do, but there is no information in web for this situation. Probably, somebody knows when Entity Framework team is going to implement attribute mapping for functions like Line To Sql does.

EF 版本:6.0.0-beta1-20521

EF version: 6.0.0-beta1-20521

谢谢!

是的,这对我有用.但仅适用于标量函数.我也需要 map 函数,它返回 IQueryable:

Yes, this works for me. But for scalar functions only. I, also, need map function, which returns IQueryable:

 IQueryable<T> MyFunction()

其中 T 是 EntityType 或 RowType 或任何类型.我根本无法做到这一点(EF 版本是 6.0.2-21211).我认为这应该以这种方式工作:

Where T is EntityType or RowType or any Type. I cannot do this at all (EF version is 6.0.2-21211). I think this should work in this way:

private static void RegisterEdmFunctions(DbModel model)
{
    var storeModel = model.GetStoreModel();
    var functionReturnValueType = storeModel.EntityTypes.Single(arg => arg.Name == "MyEntity").GetCollectionType();
    var payload =
        new EdmFunctionPayload
        {
            IsComposable = true,
            Schema = "dbo",
            StoreFunctionName = "MyFunctionName",
            ReturnParameters =
                new[]
                { 
                    FunctionParameter.Create("ReturnValue", functionReturnValueType, ParameterMode.ReturnValue)
                },
            Parameters =
                new[]
                {
                    FunctionParameter.Create("MyFunctionInputParameter", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.In)
                }
        };
    storeModel.AddItem(EdmFunction.Create(
        payload.StoreFunctionName,
        "MyFunctionsNamespace",
        DataSpace.SSpace,
        payload,
        payload.Parameters.Select(arg => MetadataProperty.Create(arg.Name, arg.TypeUsage, null)).ToArray()));
}

但还是没有运气:

  model.Compile();  // ERROR 

有没有可能?大概步骤不对吧?可能会在 EF 6.1 中添加支持.任何信息都会非常有用.

Is it possible or not? Probably steps are not right? Probably support will be added at EF 6.1. Any information will be very useful.

谢谢!

推荐答案

还没试过,但是Entity Framework 6.1 包含公共映射 API.Moozzyk 使用这个新功能实现了为EntityFramework CodeFirst 存储函数.

Haven't tried this yet, but Entity Framework 6.1 includes public mapping API. Moozzyk has implemented Store Functions for EntityFramework CodeFirst using this new functionality.

代码如下:

public class MyContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new FunctionsConvention<MyContext>("dbo"));
    }

    [DbFunction("MyContext", "CustomersByZipCode")]
    public IQueryable<Customer> CustomersByZipCode(string zipCode)
    {
        var zipCodeParameter = zipCode != null ?
            new ObjectParameter("ZipCode", zipCode) :
            new ObjectParameter("ZipCode", typeof(string));

        return ((IObjectContextAdapter)this).ObjectContext
            .CreateQuery<Customer>(
                string.Format("[{0}].{1}", GetType().Name, 
                    "[CustomersByZipCode](@ZipCode)"), zipCodeParameter);
    }

    public ObjectResult<Customer> GetCustomersByName(string name)
    {
        var nameParameter = name != null ?
            new ObjectParameter("Name", name) :
            new ObjectParameter("Name", typeof(string));

        return ((IObjectContextAdapter)this).ObjectContext.
            ExecuteFunction("GetCustomersByName", nameParameter);
    }
}

这篇关于Entity Framework 6 Code First 函数映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆