How to map exisiting sql server view with EF code first

。_饼干妹妹 提交于 2020-06-22 10:36:25

问题


i am fairly new in EF and learning EF code first. i am looking for a knowledge to map exisiting sql server view with EF code first. i have map my view with POCO but getting the below error.

when i try to fetch data from view then got the below error thrown

Additional information: The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database

my full code as follow

public class TestDBContext : DbContext
    {
        public TestDBContext()
            : base("name=TestDBContext")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new vwCustomerConfiguration());
        }

        public DbSet<vwCustomer> vwCustomer { get; set; }
    }

public class vwCustomerConfiguration : EntityTypeConfiguration<vwCustomer>
{
    public vwCustomerConfiguration()
    {
        this.HasKey(t => t.CustomerID);
        this.ToTable("vwCustomer");
    }
}

      public class vwCustomer
        {
            public int CustomerID { get; set; }
            public string FirstName { get; set; }

        }

this way i am trying to load data.

    using (var db = new TestDBContext())
    {
        var listMyViews = db.vwCustomer.ToList();
    }

guide me what i am missing in code for which error is throwing. thanks

UPDATE1

When i issue Add-Migration "My_vwCustomer" then i saw new migration code added as below one. it seems there is no migration is pending.

   public partial class My_vwCustomer : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.vwCustomers",
                c => new
                    {
                        CustomerID = c.Int(nullable: false, identity: true),
                        FirstName = c.String(),
                    })
                .PrimaryKey(t => t.CustomerID);

        }

        public override void Down()
        {
            DropTable("dbo.vwCustomers");
        }
    }

回答1:


OP's Feedback :

When i generate the view with ADO.Net Entity model wizard then everything works fine.

You can do it as shown below.

Note : I have picked the 1 to 4 from this post.

  1. Create a POCO class for the view; for example FooView
  2. Add the DbSet property in the DbContext class
  3. Use a FooViewConfiguration file to set a different name for the view (using ToTable("Foo"); in the constructor) or to set particular properties

    public class FooViewConfiguration : EntityTypeConfiguration<FooView>      
    {
       public FooViewConfiguration()
       {
        this.HasKey(t => t.Id);
        this.ToTable("myView");
      }
    

    }

  4. Add the FooViewConfiguration file to the modelBuilder, for example ovveriding the OnModelCreating method of the Context:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new FooViewConfiguration ());
    }
    
  5. According to the above configuration,now your table is this.ToTable("myView");.In other words myView.

    Here is the EF query to retrieve all the data on the myView table.

    var listMyViews = yourDbContext.myView.ToList()

Your projection may be like this :

var query = yourDbContext.myView
        .Select(v=> new
        {
            ID = v.ID,
            EmpName = v.EmpName,
            Salary = v.Salary 
        }).ToList();



回答2:


Configure view as table and use this custom generator to prevent migration generation for tables marked as views

public class SkipViewGeneration : CSharpMigrationCodeGenerator
{
    protected override void Generate(CreateTableOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    protected override void Generate(RenameTableOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    protected override void Generate(MoveTableOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    protected override void Generate(DropTableOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    protected override void Generate(AddColumnOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Table))
            base.Generate(operation, writer);
    }

    protected override void Generate(DropColumnOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Table))
            base.Generate(operation, writer);
    }

    protected override void Generate(DropPrimaryKeyOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Table))
            base.Generate(operation, writer);
    }

    protected override void Generate(AlterColumnOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Table))
            base.Generate(operation, writer);
    }

    protected override void Generate(AddPrimaryKeyOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Table))
            base.Generate(operation, writer);
    }

    protected override void Generate(AlterTableOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    protected override void Generate(CreateIndexOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    protected override void Generate(DropIndexOperation operation, IndentedTextWriter writer)
    {
        if (!IsView(operation.Name))
            base.Generate(operation, writer);
    }

    private bool IsView(string tableNameWithSchemaName)
    {
        var tableName = DatabaseName.Parse(tableNameWithSchemaName).Name;
        var schemaName = DatabaseName.Parse(tableNameWithSchemaName).Schema;
        return schemaName.Contains("View");
    }
}

Usage example

internal sealed class Configuration : DbMigrationsConfiguration<AVMSDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        CodeGenerator = new SkipViewGeneration();
    }

    protected override void Seed(AVMSDbContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method
        //  to avoid creating duplicate seed data.
    }
}

DatabaseName.Parse implementatnion you can get from Github sources



来源:https://stackoverflow.com/questions/39411531/how-to-map-exisiting-sql-server-view-with-ef-code-first

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