问题描述:
手动给表格添加字段或者新增一个表格会不会对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 "Data Source=.sqlexpress; 10 Initial Catalog=Northwind; 11 Integrated Security=True; 12 MultipleActiveResultSets=True"" 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>