Unfortunately Entity Framework Core 1.0 (formerly Entity Framework 7) does not yet support Views, and I\'m trying to \'fake\' it using a table.
Howe
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 );
});
}
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?