The model backing the 'ProductContext' context has changed since the database was created. EF6

学习《Entity Framework 6 Recipes 2nd Edition》,2-6. Splitting an Entity Among Multiple Tables中遇到几个问题

表结构:

操作

1.构造数据对象

public class Product
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int SKU { get; set; }
        public string Description { get; set; }
        public decimal Price { get; set; }
        public string ImageURL { get; set; }
    }

2.构造DBContext

public class ProductContext:DbContext
    {
        public DbSet<Product> Products { get; set; }
        public ProductContext()
            : base("name=EF6CodeFirstRecipesContext")
        {
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Product>()
            .Map(m =>
            {
                m.Properties(p => new { p.SKU, p.Description, p.Price });
                m.ToTable("Product", "Chapter2");
            })
            .Map(m =>
            {
                m.Properties(p => new { p.SKU, p.ImageURL });
                m.ToTable("ProductWebInfo", "Chapter2");
            });
        }
    }

3.生成数据

public static void InsertProduct()
        {
            //Database.SetInitializer<ProductContext>(null);

            using (var context = new ProductContext())
            {
                var product = new Product
                {
                    SKU = 147,
                    Description = "Expandable Hydration Pack",
                    Price = 19.97M,
                    ImageURL = "/pack147.jpg"
                };
                context.Products.Add(product);
                product = new Product
                {
                    SKU = 178,
                    Description = "Rugged Ranger Duffel Bag",
                    Price = 39.97M,
                    ImageURL = "/pack178.jpg"
                };
                context.Products.Add(product);
                product = new Product
                {
                    SKU = 186,
                    Description = "Range Field Pack",
                    Price = 98.97M,
                    ImageURL = "/noimage.jp"
                };
                context.Products.Add(product);
                product = new Product
                {
                    SKU = 202,
                    Description = "Small Deployment Back Pack",
                    Price = 29.97M,
                    ImageURL = "/pack202.jpg"
                };
                context.Products.Add(product);
                context.SaveChanges();
            }
            using (var context = new ProductContext())
            {
                foreach (var p in context.Products)
                {
                    Console.WriteLine("{0} {1} {2} {3}", p.SKU, p.Description,
                    p.Price.ToString("C"), p.ImageURL);
                }
            }
        }

 

做到这里,认为就能成功运行插入新的产品,简直太天真了。

 

问题一,无法连接数据库,对象模型不存在:

An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll

Additional information: The entity type Product is not part of the model for the current context.

 

解决办法:

木有仔细研究,试验了一下,发现是App.config中DB连接串的问题

原来的链接串:

<add name="EF6RecipesContext" connectionString="metadata=res://*/TestModel.csdl|res://*/TestModel.ssdl|res://*/TestModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=DST60519\SQLEXPRESS;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

修改后的连接串:

<add name="EF6CodeFirstRecipesContext" providerName="System.Data.SqlClient" connectionString="Data Source=DST60519\SQLEXPRESS;Initial Catalog=TestDB;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework"/>

EF生成链接串是  providerName="System.Data.EntityClient"

而CodeFirst生成串是  providerName="System.Data.SqlClient"

 

修改后就可以了?太天真!

 

问题二,DbContext生成异常:

经过修改后运行,发现还是会报错

The model backing the 'ProductContext' context has changed since the database was created.

Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

 

查一下网上的资料:

For those who are seeing this exception:

"The model backing the 'Production' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance."

Here is what is going on and what to do about it:

When a model is first created, we run a DatabaseInitializer to do things like create the database if it's not there or add seed data. The default DatabaseInitializer tries to compare the database schema needed to use the model with a hash of the schema stored in an EdmMetadata table that is created with a database (when Code First is the one creating the database). Existing databases won’t have the EdmMetadata table and so won’t have the hash…and the implementation today will throw if that table is missing. We'll work on changing this behavior before we ship the fial version since it is the default. Until then, existing databases do not generally need any database initializer so it can be turned off for your context type by calling:

Database.SetInitializer<YourDbContext>(null);
(http://stackoverflow.com/questions/3600175/the-model-backing-the-database-context-has-changed-since-the-database-was-crea)

所以说,在使用数据的时候,就要先戳一下连接串,告诉它我们要来了,在使用前加上:Database.SetInitializer<ProductContext>(null);

 

然后就可以走通了,yeah!

 

但是报了个错:

Violation of PRIMARY KEY constraint 'PK_Chapter2.Product'.
Cannot insert duplicate key in object 'Chapter2.Product'. The duplicate key value is (147).
The statement has been terminated.

 

原因待查ing

 

EF好难搞!!!

 

2015-8-19 14:05:52 接上

 

问题解决,

源码ProductContext:DbContext中的

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Product>()
            .Map(m =>
            {
                m.Properties(p => new { p.SKU, p.Description, p.Price });
                m.ToTable("Product", "Chapter2");
            })
            .Map(m =>
            {
                m.Properties(p => new { p.SKU, p.ImageURL });
                m.ToTable("ProductWebInfo", "Chapter2");
            });
        }

改为

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Product>()
            .Map(m =>
            {
                m.Properties(p => new { p.SKU, p.Description, p.Price });
                m.ToTable("Product");
                //m.ToTable("Product");
            })
            .Map(m =>
            {
                m.Properties(p => new { p.SKU, p.ImageURL });
                m.ToTable("ProductWebInfo");
                //m.ToTable("ProductWebInfo");
            });
        }

就可以了,就这样吧,有空再深究吧_(:з」∠)_

 

posted on 2015-08-17 17:26  Lv Jianwei  阅读(5248)  评论(0编辑  收藏  举报