如何在具有Entity Framework Core 1.0(EF7)的脚手架DbContext中使用数据库视图

时间:2016-05-27 01:35:35

标签: view entity-framework-core

不幸的是实体框架核心1.0 (以前的实体框架7)尚不支持视图,我试图假冒'它使用表格。

然而,脚手架dotnet dbcontext ef scaffold命令当前没有识别或生成视图,我想要一个允许查询视图和更新表的DbContext。有没有办法做到这一点?

这是我用来搭建DbContext的命令:

dotnet ef dbcontext scaffold -c MyStoreContext -o Model "Data Source=(local);Initial Catalog=DBNAME;Integrated Security=True" Microsoft.EntityFrameworkCore.SqlServer --force

(这会将我的所有模型类放在Model目录中,并强制它们被覆盖。)

注意:我实际想要使用View的原因是GROUP BY逻辑,在EF Core 1.0中不支持

2 个答案:

答案 0 :(得分:5)

对我来说,我的观点是在不同的架构中,所以我不得不改变模型类的属性:

using System.ComponentModel.DataAnnotations.Schema;

namespace API.DataAccess
{
    [Table("MyViewName", Schema = "SomeSchema")]
    public class MyViewName
    {
       //props
    }
}

为完整起见,实体代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyViewName>(entity =>
    {
        entity.HasKey(e => new { e.SomeColumn }).HasName("PK_FAKEKEY");
            entity.Property(e => e.SomeColumn ).IsRequired();
            entity.Property(e => e.SomeColumn2 );
            entity.Property(e => e.SomeColumn3 );
    });
}

答案 1 :(得分:1)

以下是我提出的建议:

我从DbContext创建继承的部分类,然后通过覆盖OnModelCreating方法向其添加任何新逻辑。

最终EF脚手架应该(我希望)能够为我创建视图,所以在此期间我正在调用类MyStoreContext_WithViews,所以我可以在某个时候进行搜索和替换以更新它。

此示例中的数据库视图称为RepeatOrderSummaryView

我必须在这里手动将所有列添加到我的视图类中(因为脚手架不支持它)。那现在很好。

View上没有键,但EF需要一个键,所以我只使用其中一列创建一个伪造的键。

namespace MyStore.EF.Model
{
    public partial class MyStoreContext_WithViews : MyStoreContext
    {    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<RepeatOrderSummaryView>(entity =>
            {
                entity.HasKey(e => new { e.FirstOrder_Date })
                    .HasName("PK_FAKEKEY");
            });
        }

        public virtual DbSet<RepeatOrderSummaryView> RepeatOrderSummaryView { get; set; }    
    }

    [Table("RepeatOrderSummaryView")]
    public partial class RepeatOrderSummaryView
    {
        public DateTime OrderDate { get; set; }
        public bool HasShipped { get; set; }
    }
}

然后我能够针对View成功运行此查询:

 RRStoreContext_WithViews ctx = new RRStoreContext_WithViews();
 var data = ctx.RepeatOrderSummaryView.Where(x => x.HasShipped == true);

由于这个类只是继承自我生成的DbContext(MyStoreContext),我当然可以使用所有其他脚手架的表。

未在可更新视图上进行测试 - 当然,如果您尝试此操作,则需要定义真正的PK。

因为您没有返回“真实”实体,或者必须定义具有真实密钥的项目,所以您应该使用.AsNoTracking()。我发现结果集中的结果比我预期的要少,这是因为它正在进行一次关键匹配并认为它已经在内存中有了对象。

请务必仔细测试以确保结果数量符合预期 - 否则您将遇到大问题。

What difference does .AsNoTracking() make?