12

我是使用存储过程的 EF Core 2.0 的新手。

谁能帮助如何在我的 EF Core 2.0 代码优先方法中使用存储过程?

在我之前的项目中,我有一个.edmx模型文件,我使用的上下文如下:

public IEnumerable<UserResult> GetUserResults(Entities context)
{
    if (context == null) return new List<UserResult>();
    return context.spGetUsers().Where(u => u.IsDeleted == false);
}

上下文是:

public virtual ObjectResult<UserResult> spGetUsers()
{
    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<UserResult>("spGetUsers");
}

谢谢

4

2 回答 2

10

您可以使用 FromSQL 方法:

var blogs = context.Blogs
    .FromSql("EXECUTE dbo.GetMostPopularBlogs")
    .ToList();

https://docs.microsoft.com/en-us/ef/core/querying/raw-sql

于 2018-01-11T16:25:40.080 回答
8

为了节省别人一个小时左右...

ErikEJ 的答案非常有效,但我首先需要做一些额外的工作。

在反向代码第一次迁移(到具有存储过程的现有数据库)之后,我遇到了一个问题,现有数据库上的存储过程没有返回标准表(例如 list of Blog),而是一个不同的类(例如 list of BlogTitleAndSummary)不在数据库中(因此迁移)。

这篇文章说返回必须是一个实体类型,我不确定,但是Eriks 的另一个帖子指出了我正确的方向。

要使此方案正常工作:

我创建了一个“BlogTitleAndSummary”类,将一个属性标记为[key].

例如

public class BlogTitleAndSummary
{
    [Key]
    public int BlogId { get; set; }

    public string Title { get; set; }

    public string ShortSummary { get; set; }
}

然后,我将它添加为上下文中的 DbSet,例如

public partial class BloggingContext : DbContext
{
    public BloggingContext()
    {
    }

    public BloggingContext(DbContextOptions<BloggingContext> options)
        : base(options)
    {
    }

    // Might be best to move these to another partial class, so they don't get removed in any updates.
    public virtual DbSet<BlogTitleAndSummary> BlogTitleAndSummary { get; set; }

    // Standard Tables
    public virtual DbSet<Blog> Blog { get; set; }
    ...
}

这使我能够使用以下语法来调用存储过程:

注意:我在下面的评论之后更新了这个。使用 FromSql 方法中的参数。不要对此类sql 查询使用字符串插值。

using (var ctx = new BloggingContext())
{
var dbResults = ctx.BlogTitleAndSummary.FromSql("EXEC dbo.get_bloggingSummary @UserId={0}", userId).ToList();
}
于 2018-09-13T15:31:12.697 回答