实体框架6代码第一个函数映射 [英] Entity Framework 6 Code First function mapping

查看:197
本文介绍了实体框架6代码第一个函数映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要将Entity Framework 6集成到我们的系统中,但有问题。


  1. 我想使用Code First。我不想使用数据库优先* .edmx文件的其他原因。

  2. 我使用属性映射[表],[列]和这个工作正常

  3. 数据库有许多用户定义的函数,我需要在Linq To Entities查询中使用它们。

问题是:



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



我可以在* .edmx文件中映射函数,但这意味着我不能对Entities使用属性映射:[Table],[Column]。映射必须在* .edmx或属性中完整。



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



pre> public static class函数
{
[DbFunction(CodeFirstNamespace,TestEntity)]
public static string TestEntity()
{
抛出新的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(); //这里发生错误
return compiledModel;
}
}

但有例外:



在模型生成期间检测到一个或多个验证错误:

  Edm.String::命名空间'String'是一个系统命名空间,不能被其他模式使用。选择另一个命名空间名称。 

问题是在edmType变量中。我无法正确创建ReturnType函数。
任何人都可以建议我如何将功能添加到模型中?
添加功能的界面是暴露出来的,所以应该能够做到这一点,但网络上没有这种情况的信息。
可能,有人知道Entity Framework团队将如Line To Sql这样的功能实现属性映射。



EF版本:6.0.0-beta1- 20521



谢谢!






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

  IQueryable< T> MyFunction()

其中T是EntityType或RowType或任何类型。我完全不能这样做(EF版本是6.0.2-21211)。我认为这样做应该是这样的:

  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)
},
参数=
new [ ]
{
FunctionParameter.Create(MyFunctionInputParameter,PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),ParameterMode.In)
}
};
storeModel.AddItem(EdmFunction.Create(
payload.StoreFunctionName,
MyFunctionsNamespace,
DataSpace.SSpace,
payload,
payload.Parameters。选择(arg => MetadataProperty.Create(arg.Name,arg.TypeUsage,null))。ToArray()));
}

但还是没有运气:

  model.Compile(); // ERROR 

有可能吗?
可能步骤不对?
可能会在EF 6.1中添加支持。
任何信息将非常有用。



谢谢!

解决方案

尚未尝试过,但 Entity Framework 6.1 包括公开映射API 。 Moozzyk已经使用这种新功能实施了存储EntityFramework CodeFirst功能功能。



这里是代码如下:

  public class MyContext:DbContext 
{
public DbSet< Customer>客户{get;组;

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


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

  1. I want to use Code First. I don’t want to use Database First *.edmx file for other reasons.
  2. I use attribute mapping [Table], [Column] and this works fine
  3. Database has many User-Defined Functions and I need to use them in Linq To Entities query.

Problem is:

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

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.

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

But have exception:

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.

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 version: 6.0.0-beta1-20521

Thanks!


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

 IQueryable<T> MyFunction()

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

But still no luck:

  model.Compile();  // ERROR 

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.

Thanks!

解决方案

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.

Here's what the code looks like:

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

这篇关于实体框架6代码第一个函数映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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