Skip to content

EF Core 自定义查询

如何使用 EF Core 可以参考之前的文章 【.NET Core】Entity Framework Core

其中记录了 EF Core 中无法使用自定义查询的问题,而在 5 月 30 日 发布的 EF Core 2.1 中已经实现该功能(有意思的是上面那篇 bolg 是我 5 月 29 日 写的)。

下面的实现方法来自官方的 issue Raw store access APIs: Support for ad hoc mapping of arbitrary types

实现方法

  1. 在 DBContext 的 OnModelCreating 方法中添加 modelBuilder.Query<YourModel>(); 处理;

    csharp
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Query<YourModel>();
    }
  2. 使用 Query<YourModel>().FromSql() 方法执行自定义查询;

    csharp
    public async Task<List<YourModel>> GetYourModel(string value1, Nullable<decimal> value2)
    {
        SqlParameter value1Input = new SqlParameter("@Param1", value1?? (object)DBNull.Value);
        SqlParameter value2Input = new SqlParameter("@Param2", value2?? (object)DBNull.Value);
    
        List<YourModel> getYourModel = await this.Query<YourModel>().FromSql("STORED_PROCEDURE @Param1, @Param2", value1Input, value2Input).ToListAsync();
    
        return getYourModel;
    }

查询 View

这种方法还可以用来查询 View 或 没有主键的表,如何查询 View 可以参考这篇官方的帮助文档 Query Types - EF Core _ Microsoft Docs

下面是帮助文档上的示例代码:

  1. 表模型

    cs
    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
        public string Url { get; set; }
        public ICollection<Post> Posts { get; set; }
    }
    
    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public int BlogId { get; set; }
    }
  2. 创建视图

    cs
    db.Database.ExecuteSqlCommand(
    @"CREATE VIEW View_BlogPostCounts AS 
        SELECT Name, Count(p.PostId) as PostCount from Blogs b
        JOIN Posts p on p.BlogId = b.BlogId
        GROUP BY b.Name");
  3. 查询结果模型

    cs
    public class BlogPostsCount
    {
        public string BlogName { get; set; }
        public int PostCount { get; set; }
    }
  4. OnModelCreating 中通过 modelBuilder.Query<T> 配置查询类型及映射。

    cs
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Query<BlogPostsCount>().ToView("View_BlogPostCounts")
            .Property(v => v.BlogName).HasColumnName("Name");
    }
  5. 查询数据库

    cs
    var postCounts = db.BlogPostCounts.ToList();
    
    foreach (var postCount in postCounts)
    {
        Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
        Console.WriteLine();
    }

参考

  1. Raw store access APIs: Support for ad hoc mapping of arbitrary types
  2. Query Types - EF Core _ Microsoft Docs