我想将Entity Framework 6集成到我们的系统中,但是有问题。
问题是:
我不能通过像[Table],[Column]这样的属性来映射函数。只有1个属性可用[DbFunction],它需要* .edmx文件。
我可以在* .edmx文件中映射函数,但这意味着我无法使用实体的属性映射:[Table],[Column]。必须在* .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。 任何人都可以建议我如何在模型中添加功能? 添加功能的界面是暴露的,所以它应该能够做到,但是在这种情况下web中没有信息。 可能有人知道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上添加支持。 任何信息都非常有用。
谢谢!
答案 0 :(得分:15)
尚未尝试过,但 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);
}
}
答案 1 :(得分:3)
您可以使用辅助方法从基本类型获取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
答案 2 :(得分:3)
以下是[测试]所需的所有步骤:
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 :(得分:1)
现在实体框架不是测试版,所以也许你解决了问题,但是这个解决了我的问题How to use scalar-valued function with linq to entity?