65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (12投票s)

2014年7月7日

CPOL

3分钟阅读

viewsIcon

63066

在本文中,我将讨论 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 方法的继承。

© . All rights reserved.