【问题标题】:How to map exisiting sql server view with EF code first如何首先使用 EF 代码映射现有的 sql server 视图
【发布时间】:2017-01-17 14:26:56
【问题描述】:

我是 EF 的新手,首先学习 EF 代码。我正在寻找一种知识来首先使用 EF 代码映射现有的 sql server 视图。我已经用 POCO 映射了我的视图,但出现以下错误。

当我尝试从视图中获取数据时抛出以下错误

附加信息:支持“TestDBContext”上下文的模型 自创建数据库以来已更改。考虑使用代码优先 迁移以更新数据库

我的完整代码如下

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

        }

这样我正在尝试加载数据。

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

指导我在抛出错误的代码中缺少什么。谢谢

更新1

当我发出 Add-Migration "My_vwCustomer" 时,我看到添加了新的迁移代码,如下所示。似乎没有待处理的迁移。

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

【问题讨论】:

  • 我解决了迁移生成问题。 See my answer
  • 为了防止为您的视图添加迁移,您可以在 DbContext 中使用 .ToView() 而不是 .ToTable(),在您的代码中将 this.ToTable("vwCustomer"); 更改为 this.ToView("vwCustomer");

标签: entity-framework


【解决方案1】:

将视图配置为表并使用此自定义生成器来防止为标记为视图的表生成迁移

public class SkipViewGenerator: 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");
    }
}

使用示例

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

    protected override void Seed(MyDbContextcontext)
    {
        //  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 实现你可以从 Github 获得 sources

【讨论】:

    【解决方案2】:

    OP 的反馈:

    当我使用 ADO.Net 实体模型向导生成视图时 一切正常。

    如下图所示。

    注意:我从this post中选择了1到4。

    1. 为视图创建一个POCO类;例如FooView
    2. DbContext 类中添加DbSet 属性
    3. 使用FooViewConfiguration 文件为视图设置不同的名称 (使用 ToTable("Foo"); 在构造函数中)或设置特定的 属性

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

      }

    4. 将 FooViewConfiguration 文件添加到模型构建器中,例如 oververiding Context 的 OnModelCreating 方法:

      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
          modelBuilder.Configurations.Add(new FooViewConfiguration ());
      }
      
    5. 根据上面的配置,现在你的表是 this.ToTable("myView");.换句话说myView.

      这是用于在myView 表上检索all the dataEF query

      var listMyViews = yourDbContext.myView.ToList()

    你的投影可能是这样的:

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

    【讨论】:

    • 你能否为这个场景发布一个小而完整的示例代码。
    • 查看我更新的帖子。运行代码时出现错误。查看我的完整代码。谢谢
    • 为什么我需要迁移,因为我有一个视图存在于 db 表中。迁移创建数据库对象,但如果该对象已经存在怎么办?
    • 是的,你是对的。不需要这样做。我已经删除了它。你能告诉我你的数据库视图的名称是什么吗?
    • 我的数据库视图名称是 vwCustomer。
    猜你喜欢
    • 2011-04-05
    • 2020-04-07
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多