是否可以在EF6 Code First中拨打TVF?
我首先使用EF6数据库启动了一个新项目,EF能够将TVF导入模型并调用它。
但是更新模型变得非常耗时且有问题,因为没有RI的大型只读数据库我无法处理。
所以我尝试首先使用Power Tools逆向工程工具转换为EF6代码,以生成上下文和模型类。
不幸的是,逆向工程工具没有导入TVF。
接下来,我尝试将DBFunctions从旧的Database First DbContext复制到新的Code First DbContext,但这给了我一个错误,我的TVF: “无法解析为有效的类型或函数”。
是否可以首先为TVF创建代码Fluent映射?
如果没有,是否有解决办法?
我想我可以使用SP而不是TVF,但我希望我可以使用大多数TVF来处理我遇到的有问题的数据库。
感谢任何解决方法
答案 0 :(得分:12)
现在可以了。我创建了一个自定义模型约定,允许在EF6.1中的CodeFirst中使用存储函数。该约定可在NuGet http://www.nuget.org/packages/EntityFramework.CodeFirstStoreFunctions上获得。以下是包含所有详细信息的博客帖子的链接:http://blog.3d-logic.com/2014/04/09/support-for-store-functions-tvfs-and-stored-procs-in-entity-framework-6-1/
答案 1 :(得分:9)
[测试] 使用:
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 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
答案 2 :(得分:5)
我可以使用下面的代码访问TVF。这适用于EF6。模型属性名称必须与数据库列名称匹配。
List<MyModel> data =
db.Database.SqlQuery<MyModel>(
"select * from dbo.my_function(@p1, @p2, @p3)",
new SqlParameter("@p1", new System.DateTime(2015,1,1)),
new SqlParameter("@p2", new System.DateTime(2015, 8, 1)),
new SqlParameter("@p3", 12))
.ToList();
答案 3 :(得分:2)
答案 4 :(得分:2)
我为此功能开发了一个库。你可以查看我的文章 UserTableFunctionCodeFirst。 您可以在不编写SQL查询的情况下使用您的函数。
<强>更新强>
首先,您必须添加对上述库的引用,然后您必须为您的函数创建参数类。该类可以包含任何数量和类型的参数
public class TestFunctionParams
{
[CodeFunctionAttributes.FunctionOrder(1)]
[CodeFunctionAttributes.Name("id")]
[CodeFunctionAttributes.ParameterType(System.Data.SqlDbType.Int)]
public int Id { get; set; }
}
现在你必须在DbContext中添加以下属性来调用函数并映射到属性。
[CodeFunctionAttributes.Schema("dbo")] // This is optional as it is set as dbo as default if not provided.
[CodeFunctionAttributes.Name("ufn_MyFunction")] // Name of function in database.
[CodeFunctionAttributes.ReturnTypes(typeof(Customer))]
public TableValueFunction<TestFunctionParams> CustomerFunction { get; set; }
然后你可以按照以下方式调用你的功能。
using (var db = new DataContext())
{
var funcParams = new TestFunctionParams() { Id = 1 };
var entity = db.CustomerFunction.ExecuteFunction(funcParams).ToList<Customer>();
}
这将调用您的用户定义函数并映射到实体。
答案 5 :(得分:1)
现在EntityFramework.Functions包也提供了类似的功能。这个似乎更新了。
源代码位于GitHub,introductory article解释了基本原则。