C# 实体框架代码是否首先支持存储过程?

C# 实体框架代码是否首先支持存储过程?,c#,entity-framework,stored-procedures,code-first,C#,Entity Framework,Stored Procedures,Code First,我先看了几个EF代码的演示,还没有看到EFCF如何与存储过程一起工作 如何声明将使用某些sp的方法?我是否可以将实体传递给调用sp的方法,而无需手动将实体属性映射到sp参数 另外,如果我更改了模型,会发生什么情况?它会在从模型重新创建表时删除我的sp吗?那么触发器呢 如果这些东西不受支持,是否有计划在将来支持它们?编辑:我对EF4.1(以下)的原始答案现在已过时。请查看(谁在微软的EF团队工作) @格沙普和肖恩·麦克林:你从哪里得到这些信息?您是否仍有权访问底层ObjectContext IE

我先看了几个EF代码的演示,还没有看到EFCF如何与存储过程一起工作

如何声明将使用某些sp的方法?我是否可以将实体传递给调用sp的方法,而无需手动将实体属性映射到sp参数

另外,如果我更改了模型,会发生什么情况?它会在从模型重新创建表时删除我的sp吗?那么触发器呢


如果这些东西不受支持,是否有计划在将来支持它们?

编辑:我对EF4.1(以下)的原始答案现在已过时。请查看(谁在微软的EF团队工作)


@格沙普和肖恩·麦克林:你从哪里得到这些信息?您是否仍有权访问底层ObjectContext

IEnumerable<Customer> customers = 
    ((IObjectContextAdapter)this)
    .ObjectContext.ExecuteStoreQuery<Customer>("select * from customers");
IEnumerable客户=
((IObjectContextAdapter)此)
.ObjectContext.ExecuteStoreQuery(“从客户中选择*);
用存储的proc替换“select”语句,就这样了

至于你的另一个问题:是的,不幸的是,你的s.p.会受到打击。您可能需要在代码中添加“CREATEPROCEDURE”语句

对于EF 4.2:

var customers = context.Database.SqlQuery<Customer>("select * from customers")
var customers=context.Database.SqlQuery(“选择*来自客户”)

更新:从EF6开始,EF code First确实支持插入、更新和删除的存储过程映射。可以在模型创建期间使用MapToStoredProcedures方法指定存储过程映射。我们还支持为这些操作自动搭建基本存储过程。请参见功能规格

原始答案: 在第一个版本中,我们将不支持以代码优先的方式映射模型中的存储过程,也不会有从您的类型自动生成CRUD操作的存储过程的方法。这些是我们希望在将来添加的功能

正如本线程中提到的,可以回退到ObjectContext,但是DbContext还提供了很好的API来执行本机SQL查询和命令(例如DbSet.SqlQuery、DbContext.Database.SqlQuery和DbContext.Database.ExecuteSqlCommand)。不同的SqlQuery版本具有与EF4中相同的基本物化功能(如ExecuteStoreQuery:)

希望这有帮助。

公共IList GetProductsByCategoryId(int categoryId)
    public IList<Product> GetProductsByCategoryId(int categoryId)
    {
        IList<Product> products;

        using (var context = new NorthwindData())
        {
            SqlParameter categoryParam = new SqlParameter("@categoryID", categoryId);
            products = context.Database.SqlQuery<Product>("Products_GetByCategoryID @categoryID", categoryParam).ToList();
        }

        return products;
    }

    public Product GetProductById(int productId)
    {
        Product product = null;

        using (var context = new NorthwindData())
        {
            SqlParameter idParameter = new SqlParameter("@productId", productId);
            product = context.Database.SqlQuery<Product>("Product_GetByID @productId", idParameter).FirstOrDefault();
        }

        return product;
    }
{ IList产品; 使用(var context=new NorthwindData()) { SqlParameter categoryParam=新的SqlParameter(“@categoryID”,categoryID); products=context.Database.SqlQuery(“products_GetByCategoryID@categoryID”,categoryParam.ToList(); } 退货产品; } 公共产品GetProductById(int-productId) { Product=null; 使用(var context=new NorthwindData()) { SqlParameter idParameter=新的SqlParameter(“@productId”,productId); product=context.Database.SqlQuery(“product_GetByID@productId”,idParameter).FirstOrDefault(); } 退货产品; }
更安全的解决方案是:

此类的用途是:

var testProcedureStoredProcedure = new TestProcedureStoredProcedure() { Iets = 5, NogIets = true };

var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure);
对于.NETCore(EntityFrameworkCore),我已经能够让它们工作了

可能不是最整洁的,但这确实有效

用于添加存储过程的迁移如下所示:

然后我可以用代码调用它:


后来尝试获取一些相关数据(一对多关系数据,如帖子内容),博客返回时,已填充的帖子内容已被删除。

谢谢。你能给我指出一些关于这个主题的更多信息的链接吗?你想查找ObjectContext对象上的三个执行函数(ExecuteStoreQuery、ExecuteSfunction和ExecuteStoreCommand)。我误解了这个问题。我在想,他希望创建SP的ond,并以代码为基础。您可以重写Context.OnModelCreating,并添加自定义逻辑,以便通过代码轻松创建数据库项,如存储过程。不理想,但在必要的时候,它会起作用。您不需要IObjectContextAdapter转换。DbContext可以使用内置数据库对象处理sp或自定义SQL语句:context.Database.SqlQuery(“sp_GetDummy”);顺便说一句,几天前我写了一篇博客文章,详细介绍了如何使用这些方法调用存储过程,甚至是带有输出参数的存储过程:。2013年底,EF6仍在开发中。仅仅为了改进对存储过程的支持而等了三年,唉。@divega仅仅从存储过程中选择值就有强类型支持吗?这种代码优先的方法似乎专门用于管理对象生命周期?具体来说,对于复杂的搜索,使用带有TotalRows输出参数的spFooSearch存储过程。EF路线图指出EF 6将首先支持代码的存储过程和函数。另请参见:链接不再处于活动状态,但以下是存档:
using Microsoft.EntityFrameworkCore.Migrations;
using System.Text;

namespace EFGetStarted.AspNetCore.NewDb.Migrations
{
    public partial class StoredProcedureTest : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("CREATE PROCEDURE GetBlogForAuthorName");
            sb.AppendLine("@authorSearch varchar(100)");
            sb.AppendLine("AS");
            sb.AppendLine("BEGIN");
            sb.AppendLine("-- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.");
            sb.AppendLine("SET NOCOUNT ON;");
            sb.AppendLine("SELECT  Distinct Blogs.BlogId, Blogs.Url");
            sb.AppendLine("FROM Blogs INNER JOIN");
            sb.AppendLine("Posts ON Blogs.BlogId = Posts.BlogId INNER JOIN");
            sb.AppendLine("PostsAuthors ON Posts.PostId = PostsAuthors.PostId Inner JOIN");
            sb.AppendLine("Authors on PostsAuthors.AuthorId = Authors.AuthorId");
            sb.AppendLine("Where Authors.[Name] like '%' + @authorSearch + '%'");
            sb.AppendLine("END");

            migrationBuilder.Sql(sb.ToString());
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql("DROP PROCEDURE GetBlogForAuthorName");
        }
    }
}
var blogs = _context.Blogs.FromSql("exec GetBlogForAuthorName @p0", "rod").Distinct();