How can I use database Views in a scaffolded DbContext with Entity Framework Core 1.0 (EF7)

白昼怎懂夜的黑 提交于 2019-11-30 14:18:39
Coruscate5

For me, my view was in a different schema, so I had to alter an attribute on the model class:

using System.ComponentModel.DataAnnotations.Schema;

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

For completeness, the entity code:

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

Here's what I came up with :

I create a partial class that inherits from the DbContext and then add any new logic to it by overriding the OnModelCreating method.

Eventually the EF scaffolder should (I hope) be able to create views for me, so in the interim I'm calling the class MyStoreContext_WithViews so I can do a search and replace at some point to update it.

The database view in this example is called RepeatOrderSummaryView.

I had to add all the columns manually to my view class here (since the scaffolder doesn't support it). That's fine for now.

There is no key on the View, but EF requires a key so I just create a fake one using one of the columns.

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

I was then able to successfully run this query against the View:

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

Since this class just inherits from my generated DbContext (MyStoreContext) I can of course use all the rest of the tables that were scaffolded.

Not tested on updateable views - of course if you try this you'll need a real PK defined.


Because you aren't returning 'real' entities, or necessarily items with a real key defined you should use .AsNoTracking(). I found fewer results in my result set than I expected and it was because it was doing a key match and thinking it already had the object in memory.

Be sure to test carefully to ensure the number of results is as expected - or you're going to run into big problems.

What difference does .AsNoTracking() make?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!