Entity Framework code first 手動修改數據庫的問題


問題描述:

手動給表格添加字段或者新增一個表格會不會對DBContext產生影響呢?

 

解決方案:

不會產生影響,如果我們不想code中的model不和數據庫中增加的保持一致,可以不添加對應的字段和model,但是如果我們需要保持一致,如何做呢

步驟如下:

  a. 將Model手動改成與數據庫一致

  b. 在執行DbContext的實例化前加一句    Database.SetInitializer<BloggingContext>(null); 

  c. 如果以后你需要在添加model ,則如果你把之前你手動改動與數據庫同步的部分注釋掉,然后再利用add-migration addmodel ;update-database來更新仍然是可以用的

 

下面的例子展示了如何做:

手動在數據更改之前:

 1     public class Blog
 2     {
 3         public int BlogId { get; set; }
 4         public string Name { get; set; }
 5 
 6         public string Url { get; set; }
 7         public virtual List<Post> Posts { get; set; }
 8     }
 9 
10     public class User
11     {
12         [Key]
13         public int UserId { get; set; }
14         public string Username { get; set; }
15         public string DisplayName { get; set; }
16         //public int? age { get; set; }
17         //public string interest { get; set; }
18     }
19 
20     public class School
21     {
22         public int SchoolId { get; set; }
23 
24         public string SchoolName { get; set; }
25 
26         public int SchoolLevel { get; set; }
27     }
28 
29     public class Post
30     {
31         public int PostId { get; set; }
32         public string Title { get; set; }
33         public string Content { get; set; }
34 
35         public int BlogId { get; set; }
36         public virtual Blog Blog { get; set; }
37     }
38 
39     public class Tutorial
40     {
41         [Key]
42         public int Id { get; set; }
43 
44         public int Name { get; set; }
45     }
46 
47     public class BloggingContext : DbContext
48     {
49         public DbSet<Blog> Blogs { get; set; }
50         public DbSet<Post> Posts { get; set; }
51 
52         public DbSet<User> Users { get; set; }
53 
54          public DbSet<Tutorial> Tutorials { get; set; }
55         //public DbSet<School> Schools { get; set; }
56 
57         protected override void OnModelCreating(DbModelBuilder modelBuilder)
58         {
59             modelBuilder.Entity<User>().Property(u => u.DisplayName).HasColumnName("display_name");
60             modelBuilder.Entity<User>().Property(u => u.Username).HasColumnName("user_name");
61         }
62     }

數據庫中的表:

 

手動添加了表Schools並且更改了Users表中的字段

 

自己手動更改Model並保持與數據庫同步

 1     public class Blog
 2     {
 3         public int BlogId { get; set; }
 4         public string Name { get; set; }
 5 
 6         public string Url { get; set; }
 7         public virtual List<Post> Posts { get; set; }
 8     }
 9 
10     public class User
11     {
12         [Key]
13         public int UserId { get; set; }
14         public string Username { get; set; }
15         public string DisplayName { get; set; }
16         public int? age { get; set; }
17         public string interest { get; set; }
18     }
19 
20     public class School
21     {
22         public int SchoolId { get; set; }
23 
24         public string SchoolName { get; set; }
25 
26         public int SchoolLevel { get; set; }
27     }
28 
29     public class Post
30     {
31         public int PostId { get; set; }
32         public string Title { get; set; }
33         public string Content { get; set; }
34 
35         public int BlogId { get; set; }
36         public virtual Blog Blog { get; set; }
37     }
38 
39     public class Tutorial
40     {
41         [Key]
42         public int Id { get; set; }
43 
44         public int Name { get; set; }
45     }
46 
47     public class BloggingContext : DbContext
48     {
49         public DbSet<Blog> Blogs { get; set; }
50         public DbSet<Post> Posts { get; set; }
51 
52         public DbSet<User> Users { get; set; }
53 
54         public DbSet<Tutorial> Tutorials { get; set; }
55         public DbSet<School> Schools { get; set; }
56 
57         protected override void OnModelCreating(DbModelBuilder modelBuilder)
58         {
59             modelBuilder.Entity<User>().Property(u => u.DisplayName).HasColumnName("display_name");
60             modelBuilder.Entity<User>().Property(u => u.Username).HasColumnName("user_name");

 

如果你調用add-migration and update-database 會提示 There is already an object named 'Schools' in the database.

所以你去訪問數據庫時會出現錯誤:

            using (var db = new BloggingContext())
            {


                //var query2 = from b in db.Schools
                //             orderby b.SchoolName
                //             select b;


                //var schoolList = query2.ToList();

                var query1 = from b in db.Users
                            orderby b.Username
                            select b;

                var userList = query1.ToList();

                // Create and save a new Blog 
                Console.Write("Enter a name for a new Blog: ");
                var name = Console.ReadLine();

                var user = new User { UserId = 0, Username = name };

                db.Users.Add(user);
                db.SaveChanges();




                //var blog = new Blog { Name = name };
                //db.Blogs.Add(blog);


                //db.SaveChanges();

                // Display all Blogs from the database 
                var query = from b in db.Blogs
                            orderby b.Name
                            select b;

                Console.WriteLine("All blogs in the database:");
                foreach (var item in query)
                {
                    Console.WriteLine(item.Name);
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }

會產生異常:

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

Additional information: The model backing the 'BloggingContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

 

如果在using (var db = new BloggingContext())前加上Database.SetInitializer<BloggingContext>(null);就不會報錯

但是如果以后想添加Model的話,怎么做呢,我們可以將之前你添加與手動添加School表和修改user表的一些信息注釋掉,migration文件也刪除,然后你在添加model再去執行數據遷移就不會出問題,遷移好了后,你在重新反注釋即可。

 

2. 數據庫連接字符串的更改

在 Code First 模式下按約定使用連接

如果您還沒有在應用程序中進行任何其他配置,則對 DbContext 調用無參數構造函數將會導致 DbContext 使用按約定創建的數據庫連接在 Code First 模式下運行。例如:

 1 namespace Demo.EF 
 2 { 
 3     public class BloggingContext : DbContext 
 4     { 
 5         public BloggingContext() 
 6         // C# will call base class parameterless constructor by default 
 7         { 
 8         } 
 9     } 
10 }

 

在此示例中,DbContext 使用派生上下文類 Demo.EF.BloggingContext 的命名空間限定名稱作為數據庫名稱,並使用 SQL Express 或 LocalDb 為此數據庫創建連接字符串。如果同時安裝了這兩個數據庫,將使用 SQL Express。

默認情況下,Visual Studio 2010 包含 SQL Express,Visual Studio 2012 包含 LocalDb。安裝期間,EntityFramework NuGet 包會檢查哪個數據庫服務器可用。隨后 NuGet 包將設置按約定創建連接時 Code First 所使用的默認數據庫服務器,以此更新配置文件。如果 SQL Express 正在運行,將使用它。如果 SQL Express 不可用,則 LocalDb 將注冊為默認數據庫。如果配置文件已包含默認連接工廠設置,則不會更改該文件。

在 Code First 模式下按約定和指定數據庫名稱使用連接

如果您尚未在應用程序中進行任何其他配置,在通過要使用的數據庫名稱對 DbContext 調用字符串構造函數時,將會導致 DbContext 使用按約定創建的與該名稱數據庫的連接在 Code First 模式下運行。例如:

public class BloggingContext : DbContext 
{ 
    public BloggingContext() 
        : base("BloggingDatabase") 
    { 
    } 
}

 

在此示例中,DbContext 使用“BloggingDatabase”作為數據庫名稱,並使用 SQL Express(隨 Visual Studio 2010 安裝)或 LocalDb(隨 Visual Studio 2012 安裝)為此數據庫創建連接字符串。如果同時安裝了這兩個數據庫,將使用 SQL Express。

 

在 Code First 模式下使用 app.config/web.config 文件中的連接字符串

可以選擇將連接字符串放入 app.config 或 web.config 文件中。例如:

<configuration> 
  <connectionStrings> 
    <add name="BloggingCompactDatabase" 
         providerName="System.Data.SqlServerCe.4.0" 
         connectionString="Data Source=Blogging.sdf"/> 
  </connectionStrings> 
</configuration>

 

這是一種指示 DbContext 使用數據庫服務器而非 SQL Express 或 LocalDb 的簡單方法 — 上例指定了 SQL Server Compact Edition 數據庫。

如果連接字符串的名稱與上下文的名稱(帶或不帶命名空間限定)相同,則使用無參數構造函數時 DbContext 會找到該連接字符串。如果連接字符串名稱與上下文名稱不同,則可通過將連接字符串名稱傳遞給 DbContext 構造函數,指示 DbContext 在 Code First 模式下使用此連接。例如:

1 public class BloggingContext : DbContext 
2 { 
3     public BloggingContext() 
4         : base("BloggingCompactDatabase") 
5     { 
6     } 
7 }

 

或者,也可以對傳遞給 DbContext 構造函數的字符串使用 “name=<連接字符串名稱>”格式。例如:

1 public class BloggingContext : DbContext 
2 { 
3     public BloggingContext() 
4         : base("name=BloggingCompactDatabase") 
5     { 
6     } 
7 }

 

使用此形式可以明確要求在配置文件中查找連接字符串。如果未找到具有給定名稱的連接字符串,則將引發異常。

 

Database/Model First 使用 app.config/web.config 文件中的連接字符串

使用 EF 設計器創建的模型不同於 Code First,因為該模型事先已存在,而不是在應用程序運行時從代碼生成的。該模型通常在項目中以 EDMX 文件形式存在。

Designer 會將 EF 連接字符串添加到 app.config 或 web.config 文件中。此連接字符串十分特殊,因為它說明了如何在 EDMX 文件中查找信息。例如:

 1 <configuration>  
 2   <connectionStrings>  
 3     <add name="Northwind_Entities"  
 4          connectionString="metadata=res://*/Northwind.csdl|  
 5                                     res://*/Northwind.ssdl|  
 6                                     res://*/Northwind.msl;  
 7                            provider=System.Data.SqlClient;  
 8                            provider connection string=  
 9                                &quot;Data Source=.\sqlexpress;  
10                                      Initial Catalog=Northwind;  
11                                      Integrated Security=True;  
12                                      MultipleActiveResultSets=True&quot;"  
13          providerName="System.Data.EntityClient"/>  
14   </connectionStrings>  
15 </configuration>

 

EF 設計器還將生成一些代碼,指示 DbContext 通過將連接字符串名稱傳遞給 DbContext 構造函數來使用此連接。例如:

1 public class NorthwindContext : DbContext 
2 { 
3     public NorthwindContext() 
4         : base("name=Northwind_Entities") 
5     { 
6     } 
7 }

 

由於連接字符串是包含待用模型詳細信息的 EF 連接字符串,因此 EF DbContext 十分清楚要加載現有模型(而不是使用 Code First 從代碼計算模型)。

 

其他 DbContext 構造函數選項

DbContext 類包含支持其他一些更高級方案的其他構造函數和使用模式。其中一些選項有:

    • 可以使用 DbModelBuilder 類構建 Code First 模型,而不實例化 DbContext 實例。這樣會生成 DbModel 對象。隨后,在准備好創建 DbContext 實例時,可以將此 DbModel 對象傳遞給某一 DbContext 構造函數。
    • 可以將完整連接字符串傳遞給 DbContext,而不僅僅傳遞數據庫或連接字符串名稱。此連接字符串默認用於 System.Data.SqlClient 提供程序;可以通過在 context.Database.DefaultConnectionFactory 上設置不同的 IConnectionFactory 實現來更改此行為。
    • 可以通過將現有 DbConnection 對象傳遞給 DbContext 構造函數來使用該對象。如果連接對象是 EntityConnection 的實例,則將使用連接中指定的模型,而不使用 Code First 計算模型。如果該對象是其他某一類型(例如 SqlConnection)的實例,則上下文將在 Code First 模式下使用該對象。
    • 可以通過將現有 ObjectContext 傳遞給 DbContext 構造函數,創建包裝現有上下文的 DbContext。對於使用 ObjectContext 但希望在其中一部分利用 DbContext 的現有應用程序,這一點十分有用。

 

SQL 使用的連接字符串:

1 <connectionStrings>
2 <!--<add name="eRebateContext" connectionString="Database=eRebateTest;Server=10.40.15.16;uid=sa;pwd=a8@accnmis;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>
3 <add name="NotesConnection" connectionString="server=10.40.15.16;database=Dealer;uid=sa;pwd=a8@accnmis;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>-->
4 <add name="eRebateContext" connectionString="Database=eRebate;Server=V-BLCHEN-02;Trusted_connection=Yes;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
5 <add name="NotesConnection" connectionString="Database=Dealer;Server=V-BLCHEN-02;Trusted_connection=Yes;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
6 <!--<add name="eRebateContext" connectionString="Database=eRebate;Server=10.40.15.81;user=sa;password=mis" providerName="System.Data.SqlClient"/>
7 <add name="NotesConnection" connectionString="Database=Dealer;Server=10.40.15.81;user=sa;password=mis" providerName="System.Data.SqlClient"/>-->
8 </connectionStrings>

Mysql 使用的連接字符串 (install Mysql.data.entity)

1   <connectionStrings>
2     <add name="JdCloudDbContext" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;database=jd_cloud_data;UID=root;password=root;"/>
3   </connectionStrings>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM