支持EF6 Code First中的表值函数?

Pat*_*ick 15 entity-framework entity-framework-6

是否可以在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来处理我遇到的有问题的数据库.

感谢任何解决方法的想法

Paw*_*wel 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-框架-6-1 /


Nin*_*ina 10

[测试]使用:

Install-Package EntityFramework.CodeFirstStoreFunctions
Run Code Online (Sandbox Code Playgroud)

为输出结果声明一个类:

    public class MyCustomObject
        {
            [Key]
            public int Id { get; set; }
            public int Rank { get; set; }
        }
Run Code Online (Sandbox Code Playgroud)

在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);
}
Run Code Online (Sandbox Code Playgroud)

public DbSet<MyCustomObject> SearchResults { get; set; }
Run Code Online (Sandbox Code Playgroud)

到你的DbContext类

添加覆盖OnModelCreating方法:

 modelBuilder.Conventions.Add(new FunctionsConvention<MyContextType>("dbo"));
Run Code Online (Sandbox Code Playgroud)

现在你可以用这样的表值函数调用/ join:

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
Run Code Online (Sandbox Code Playgroud)

  • **注意** 如果返回类型不是表(因此将其添加为“DbSet”将尝试在迁移中创建它)将其添加为复杂类型。`[ComplexType]` 属性不起作用,但 Fluent API 可以:在上下文类型的 `OnModelBuilding` 中添加 `modelBuilder.ComplexType&lt;MyCustomerObject&gt;();` (2认同)

use*_*854 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();
Run Code Online (Sandbox Code Playgroud)

  • CodeFirstStoreFunctions是第三方NuGet包,而不是标准的EF功能.看下面的示例代码,它只是SqlQuery的一个包装,带有一些花哨的东西.许多地方不允许将第三方代码下载到代码库中,因此在MSFT将其捆绑到下一个EF版本之前,它们实际上不是那些人的选项. (3认同)
  • 这个答案对我来说是最好的,因为我不想过多地传递第三方解决方案而且每次ORM都会在一段时间内失效.这种方法只是特别发现,因为它可以防止sql注入并打开漏洞抽象,并使开发人员意识到如果需要,他总是可以在这里和那里使用一点sql. (3认同)
  • 您发布的代码甚至与实体框架相关. (2认同)
  • 是的,使用 SQL 查询可以完成任何事情,但通常有 EF 方法和 SQL 查询方法来执行此操作。如果有 EF 方式可以执行,则显然使用 EF 方式执行;如果 EF 不支持 EF 的创建者创建的 SQL 查询,则显然使用 EF 方式执行。我的观点是,在撰写本文时,没有办法使用 EF 来完成此操作,这是一种方法。如果您不同意这一点,请发布一个答案,您将如何严格使用 EF 来做到这一点。通过使用 EF 来执行此操作,您可以获得自动对象映射、ORM 的 O 和 M。 (2认同)

Paw*_*wel 2

实际上,我开始在 EF6.1 中研究它,并且有一些可以在夜间构建上运行的东西。检查这个这个