Entity Framework 中初始化数据库的各种策略






4.89/5 (12投票s)
在本文中,我将讨论 Entity Framework 中各种数据库初始化策略
引言
这是本系列的第二篇文章。在我们的第一篇文章中,我们已经了解了如何在 Entity Framework 中使用 Code First 方法入门?你可以在这里阅读:Entity Framework 中的 Code First 方法。好的,我们了解了 Code First 和其他方法,并了解了何时以及如何在各种开发场景中发挥作用。在讨论中,我们已经看到,在 Code First 方法中,首先需要编写代码,然后才能生成数据库。这种方法非常清晰直接。现在,让我们思考一下,当我们已经编写代码并生成数据库,然后我们决定更改数据库中的某些内容时,会发生什么情况。这可能是添加一个新属性(在数据库关系模式中称为列)或删除旧属性。或者我们可能想更改表之间的关系。现在,数据库已经创建好了,我们应该修改现有数据库并创建一个新数据库吗?Entity Framework 提供了四种选项来处理这种情况。它们是
- 如果数据库不存在则创建数据库
- 始终创建数据库
- 当模型更改时创建数据库
- 自定义
在本文中,我们将逐一讨论,并了解如何在 Entity Framework Code First 方法中实现。如果数据库不存在则创建数据库。这是第一次运行的尝试,通常一开始数据库没有创建,我们可以在上下文类中设置设置,因此当数据库不存在时,该设置非常有用。看看下面的代码
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace CodeFirst
{
public class Person
{
[Key]
public int PersonId { get; set; }
[Required]
[MaxLength(10)]
public string Name { get; set; }
public string surname { get; set; }
}
public class TestContext : DbContext
{
public TestContext()
: base("DBConnectionString")
{
//Create database always, even If exists
Database.SetInitializer<TestContext>(new CreateDatabaseIfNotExists<TestContext>());
}
public DbSet<Person> Students { get; set; }
}
}
实现非常简单,我们创建了 Person
模型和 TestContext
类,以使用 Code First 方法初始化数据库。请注意,我们正在通过构造函数传递连接字符串,连接字符串应该在应用程序的 *web.config* 文件中配置。这是我的。
<connectionStrings>
<add name="DBConnectionString"
connectionString="Data Source=SERVERNAME;Initial Catalog=PersonDB;Integrated Security=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>
只需根据您的环境配置您的连接字符串,一旦您运行应用程序,您将看到它已创建如下数据库
始终创建数据库
在这种方法中,数据库将始终创建,无论它是否已经存在。因此,在每次运行代码时,如果数据库存在,它将删除该数据库,并创建一个全新的数据库。因此,当创建全新的数据库时,如果存在任何旧数据,显然会丢失。因此,请务必确保在这种方法的开发环境中始终提供数据库种子数据代码。这是始终创建数据库方法的配置。此示例中的模型 (Person
) 也相同。
public class TestContext : DbContext
{
public TestContext()
: base("DBConnectionString")
{
//Create database always, even If exists
Database.SetInitializer<TestContext>(new DropCreateDatabaseAlways<TestContext>());
}
public DbSet<Person> Students { get; set; }
}
如果模型更改
这是另一种很棒的数据库生成方法,我非常关心。当代码中的模型与数据库模型不匹配时,将生成数据库。这是设置该方法的代码。
public class TestContext : DbContext
{
public TestContext()
: base("DBConnectionString")
{
//Create database always, even If exists
Database.SetInitializer<TestContext>(new DropCreateDatabaseIfModelChanges<TestContext>());
}
public DbSet<Person> Students { get; set; }
}
自定义初始化
这是最后一个也是最重要的一个。这种方法非常灵活,并且完全由开发人员掌控。开发人员可以决定何时生成数据库,并根据新代码创建新数据库。看看下面的实现
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace CodeFirst
{
public class Person
{
[Key]
public int PersonId { get; set; }
[Required]
[MaxLength(10)]
public string Name { get; set; }
public string surname { get; set; }
}
public class PersonDBInitializer : DropCreateDatabaseAlways<TestContext>
{
protected override void Seed(TestContext context)
{
base.Seed(context);
}
}
public class TestContext : DbContext
{
public TestContext()
: base("DBConnectionString")
{
//Create database always, even If exists
Database.SetInitializer<TestContext>(new PersonDBInitializer());
}
public DbSet<Person> Students { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var ctx = new TestContext())
{
new PersonDBInitializer().InitializeDatabase(ctx);
}
}
}
}
在这种方法中,我们引入了另一个名为 DBInitializer
的类,并通过创建 PersonDBInitializer
类的对象来调用 SetInitialise
方法。
将数据种子到数据库中
这是我想要介绍的一个额外主题,即在全新的数据库中设置一些默认数据的机制。有时,当我们想要一些默认数据以及新创建的数据库时,它非常有用。看看下面的代码
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace CodeFirst
{
public class Person
{
[Key]
public int PersonId { get; set; }
[Required]
[MaxLength(10)]
public string Name { get; set; }
public string surname { get; set; }
}
public class PersonDBInitializer : DropCreateDatabaseAlways<TestContext>
{
List<Person> persons = new List<Person>();
public PersonDBInitializer()
{
persons.Add(new Person { Name = "sourav", surname = "kayal" });
persons.Add(new Person { Name = "foo", surname = "bar" });
}
protected override void Seed(TestContext context)
{
foreach (Person p in persons)
{
context.Students.Add(p);
}
context.SaveChanges();
base.Seed(context);
}
}
public class TestContext : DbContext
{
public TestContext()
: base("DBConnectionString")
{
//Create database always, even If exists
Database.SetInitializer<TestContext>(new PersonDBInitializer());
}
public DbSet<Person> Students { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var ctx = new TestContext())
{
new PersonDBInitializer().InitializeDatabase(ctx);
}
}
}
}
这段代码将在 Person
表中设置默认数据。
总结
在本文中,我们已经看到了在 Code First 方法中初始化数据库的各种方法。希望它会对你有所帮助。在下一篇文章中,我感兴趣的是讨论 Entity Framework 中 Code First 方法的继承。