Entity Framework 6 Code First 函数映射
Posted
技术标签:
【中文标题】Entity Framework 6 Code First 函数映射【英文标题】:Entity Framework 6 Code First function mapping 【发布时间】:2013-05-20 04:45:12 【问题描述】:我想将 Entity Framework 6 集成到我们的系统中,但是遇到了问题。
-
我想使用 Code First。由于其他原因,我不想使用 Database First *.edmx 文件。
我使用属性映射 [Table]、[Column],效果很好
数据库有很多用户定义的函数,我需要在 Linq To Entities 查询中使用它们。
问题是:
我无法通过 [Table]、[Column] 等属性映射函数。只有 1 个属性可用 [DbFunction],需要 *.edmx 文件。
我可以在 *.edmx 文件中进行函数映射,但这意味着我不能对实体使用属性映射:[表]、[列]。 *.edmx 或属性中的映射必须是完整的。
我尝试通过此代码创建 DbModel 并添加功能:
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;
但有例外:
在模型生成过程中检测到一个或多个验证错误:
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 之类的函数实现属性映射。
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)
,
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 中添加支持。 任何信息都会非常有用。
谢谢!
【问题讨论】:
您有一个数据库并想先通过代码访问?那么就不需要模型了。见msdn.microsoft.com/en-us/data/jj200620 【参考方案1】:还没有尝试过,但是Entity Framework 6.1 包含public mapping API。 Moozzyk 使用这个新功能实现了Store Functions for EntityFramework CodeFirst。
代码如下:
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);
【讨论】:
我可以用这个返回一个不同于表类型的类型吗? IE: 我想返回 ObjectResult以下是所需的所有步骤 [已测试]:
Install-Package EntityFramework.CodeFirstStoreFunctions
为输出结果声明一个类:
public class MyCustomObject
[Key]
public int Id get; set;
public int Rank get; set;
在你的 DbContext 类中创建一个方法
[DbFunction("MyContextType", "SearchSomething")]
public virtual IQueryable<MyCustomObject> SearchSomething(string keywords)
var keywordsParam = new ObjectParameter("keywords", typeof(string))
Value = keywords
;
return (this as IObjectContextAdapter).ObjectContext
.CreateQuery<MyCustomObject>(
"MyContextType.SearchSomething(@keywords)", keywordsParam);
添加
public DbSet<MyCustomObject> SearchResults get; set;
到你的 DbContext 类
添加覆盖的OnModelCreating
方法:
modelBuilder.Conventions
.Add(new CodeFirstStoreFunctions.FunctionsConvention<MyContextType>("dbo"));
现在你可以打电话/加入 像这样的表值函数:
CREATE FUNCTION SearchSomething
(
@keywords nvarchar(4000)
)
RETURNS TABLE
AS
RETURN
(SELECT KEY_TBL.RANK AS Rank, Id
FROM MyTable
LEFT JOIN freetexttable(MyTable , ([MyColumn1],[MyColumn2]), @keywords) AS KEY_TBL
ON MyTable.Id = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 0
)
GO
【讨论】:
【参考方案3】:现在实体框架不是测试版,所以也许你解决了你的问题,但是这个解决了我的问题How to use scalar-valued function with linq to entity?
【讨论】:
问题是关于使用代码优先方法的函数,您已经链接到带有 .edmx 文件的解决方案,但事实并非如此。 问题是没有办法使用代码优先方法在实体框架中使用标量函数,我试图这样做,最后不得不使用链接中建议的内容跨度> 我刚刚尝试了实体框架 6 的工具,并允许我使用代码优先方法【参考方案4】:您可以使用辅助方法从原始类型中获取 Store 类型:
public static EdmType GetStorePrimitiveType(DbModel model, PrimitiveTypeKind typeKind)
return model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage(
PrimitiveType.GetEdmPrimitiveType(typeKind))).EdmType;
在您的示例中,您必须更改返回参数的类型:
var edmType = GetStorePrimitiveType(model, PrimitiveTypeKind.String);
我在这里找到了我需要的帮助: http://entityframework.codeplex.com/discussions/466706
【讨论】:
如何映射可组合函数,其结果可查询任何类型? 我不确定你在问什么。我使用上面的代码将标量 DB 函数映射到 C# 方法以比较并发字段 (byte[]),并使用该方法编写查询。也许我原来的答案会有所帮助:***.com/a/20225824/2808810以上是关于Entity Framework 6 Code First 函数映射的主要内容,如果未能解决你的问题,请参考以下文章
Entity Framework 6 Code First +MVC5+MySql/Oracle使用过程中的两个问题
Entity Framework 6 + Code First + Oracle 12c 的示例
Code First Entity Framework 6化被动为主动之explicit loading模式实战分析( 附源码)
如何使用 Entity Framework 6 Code First 设置默认值约束?