Entity Framework Code First是否支持存储过程?

时间:2011-01-30 20:18:10

标签: c# entity-framework stored-procedures code-first

我观看了几次EF Code First的演示,还没有看到EFCF如何与存储过程协同工作。

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

另外,如果我改变模型会发生什么?它会在从模型中重新创建表格时丢失我的sp吗?触发器呢?

如果不支持这些内容,是否有计划在将来支持这些内容?

4 个答案:

答案 0 :(得分:66)

编辑:我对EF4.1(下方)的原始答案现已过时。请参阅the answer below from Diego Vega(在Microsoft的EF团队工作)!


@gsharp和Shawn Mclean:你在哪里得到这些信息?你是否仍然可以访问底层的ObjectContext?

IEnumerable<Customer> customers = 
    ((IObjectContextAdapter)this)
    .ObjectContext.ExecuteStoreQuery<Customer>("select * from customers");

将“select”语句替换为存储过程,然后就可以了。

关于你的另一个问题:是的,不幸的是你的s.p.将被破坏。您可能需要在代码中添加“CREATE PROCEDURE”语句。

对于EF 4.2:

var customers = context.Database.SqlQuery<Customer>("select * from customers")

答案 1 :(得分:50)

更新:从EF6开始,EF Code First支持插入,更新和删除的存储过程映射。您可以使用MapToStoredProcedures方法在模型创建期间指定存储过程映射。我们还支持这些操作的基本存储过程的自动脚手架。请参阅功能规范here

原始回答: 我们将不支持在第一版中的Code-First中映射模型中的存储过程,也不会为您的类型自动生成CRUD操作的存储过程。这些是我们希望将来添加的功能。

正如在这个线程中提到的那样,可以回退到ObjectContext,但是DbContext也提供了很好的API来执行本机SQL查询和命令(例如DbSet.SqlQuery,DbContext.Database.SqlQuery和DbContext.Database.ExecuteSqlCommand) 。不同的SqlQuery版本具有与EF4中相同的基本实现功能(如ExecuteStoreQuery:http://msdn.microsoft.com/en-us/library/dd487208.aspx)。

希望这有帮助。

答案 2 :(得分:31)

    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;
    }

答案 3 :(得分:2)

对于.NET Core(EntityFrameworkCore),我已经能够让它们正常工作。

可能不是最好的,但这绝对有效。

添加存储过程的迁移类似于this

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");
        }
    }
}

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

var blogs = _context.Blogs.FromSql("exec GetBlogForAuthorName @p0", "rod").Distinct();

后来尝试获取一些相关数据(一对多关系数据,例如发布内容),并且博客回来时已填写的帖子内容被检测到。