EF Core 2.0如何使用SQL存储过程

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

感谢

2个回答

10

非常感谢。所以,当所有迁移都执行完毕后,我只需要在数据库中创建存储过程,对吗? - Mukil Deepthi
是的,或者您可以使用Sql()方法在迁移期间创建它们(编辑迁移)。 - ErikEJ
非常感谢。很抱歉在同一条线上再问你一件事。目前我的“UserResult”不是数据库中的实体。它是[NotMapped]。在这种情况下,我该如何执行查询?就像您的示例context.Blogs一样,我没有context.UserResults。谢谢。 - Mukil Deepthi
阅读文档,你会发现目前这是不可能的。 - ErikEJ
5
如果您指的是查询类型的使用,该功能现在已经包含在EF Core 2.1中:https://learn.microsoft.com/en-us/ef/core/modeling/query-types - Elijah Lofgren

8
为了节省其他人一个小时左右的时间...
ErikEJ的答案是完美的,但我需要做一些额外的工作。
在进行反向代码迁移(到具有存储过程的现有数据库)之后,我遇到了一个问题,即现有数据库上的存储过程没有返回标准表格(例如Blog列表),而是一个不同的类(例如BlogTitleAndSummary列表),这个类不在数据库中(因此也不在迁移范围内)。
此帖子指出返回值必须是实体类型,我对此表示怀疑,但Eriks的另一个帖子为我指明了方向。
为了让这种情况正常工作:
我创建了一个"BlogTitleAndSummary"类,并将其中一个属性标记为[key]
例如:
public class BlogTitleAndSummary
{
    [Key]
    public int BlogId { get; set; }

    public string Title { get; set; }

    public string ShortSummary { get; set; }
}

然后,我将其作为Context的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方法中使用params。不要对sql查询使用字符串插值。
using (var ctx = new BloggingContext())
{
var dbResults = ctx.BlogTitleAndSummary.FromSql("EXEC dbo.get_bloggingSummary @UserId={0}", userId).ToList();
}

1
只是想提醒你和其他人,无论你的存储过程写得多么好,你特定的例子string query = @"EXEC [dbo].[get_bloggingSummary] @User = N'" + userId + @"';都是不安全的,你不应该忽视这个警告。查询应该通过将参数单独传递FromSql("exec dbo.get_bloggingSummary {0}", userId)进行参数化,或使用字符串插值FromSql($"exec dbo.get_bloggingSummary {userId}"),EF Core会自动为您参数化。 - sgbj
1
@sgbj - 谢谢。我已经根据您的评论更新了示例(和我的代码!)。它确实消除了关于 SQL 注入攻击的警告。 - JsAndDotNet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接