数据库配置约定

连接字符串约定

默认配置

如果您还没有在应用程序中进行任何其他配置,则对 DbContext 调用无参数构造函数将会导致 DbContext 使用按约定创建的数据库连接在 Code First 模式下运行。例如:

namespaceDemo.EF
{
  public class BloggingContext: DbContext
  {
    publicBloggingContext()

    // C# will callbase class parameterless constructor by default
    {

    }
  }
}

在此示例中,DbContext使用派生上下文类 Demo.EF.BloggingContext 的命名空间限定名称作为数据库名称,并使用 SQL Express 或 LocalDb 为此数据库创建连接字符串。如果同时安装了这两个数据库,将使用 SQL Express。

默认情况下,VisualStudio 2010 包含 SQLExpress,VisualStudio 2012 包含LocalDb。安装期间,EntityFrameworkNuGet 包会检查哪个数据库服务器可用。随后 NuGet 包将设置按约定创建连接时 Code First 所使用的默认数据库服务器,以此更新配置文件。如果 SQL Express 正在运行,将使用它。如果 SQL Express 不可用,则 LocalDb 将注册为默认数据库。如果配置文件已包含默认连接工厂设置,则不会更改该文件。

指定数据库名称

如果您尚未在应用程序中进行任何其他配置,在通过要使用的数据库名称对 DbContext 调用字符串构造函数时,将会导致 DbContext 使用按约定创建的与该名称数据库的连接在 Code First 模式下运行。例如:

namespaceDemo.EF
{
  public class BloggingContext: DbContext
  {
    public BloggingContext()
      : base("BloggingDatabase")
    {

    }
  }
}

在此示例中,DbContext使用“BloggingDatabase”作为数据库名称,并使用 SQL Express(随Visual Studio 2010 安装)或LocalDb(随Visual Studio 2012 安装)为此数据库创建连接字符串。如果同时安装了这两个数据库,将使用 SQL Express。

指定连接字符串

可以选择将连接字符串放入 app.config 或web.config 文件中。例如:

<configuration>
  <connectionStrings>
    <addname="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 在 CodeFirst 模式下使用此连接。例如:

public class BloggingContext: DbContext
{
  public BloggingContext()
    : base("BloggingCompactDatabase")
  {

  }
}

或者,也可以对传递给DbContext 构造函数的字符串使用 “name=<连接字符串名称>”格式。例如:

public class BloggingContext: DbContext
{
  publicBloggingContext()
    : base("name=BloggingCompactDatabase")
  {

  }
}

使用此形式可以明确要求在配置文件中查找连接字符串。如果未找到具有给定名称的连接字符串,则将引发异常。

数据库初始化策略:

数据库创建是由策略来控制的,有如下四种策略:

1. CreateDatabaseIfNotExists:这是默认的策略。如果数据库不存在,那么就创建数据库。但是如果数据库存在了,而且实体发生了变化,就会出现异常。

2. DropCreateDatabaseIfModelChanges:此策略表明,如果模型变化了,数据库就会被重新创建,原来的数据库被删除掉了。

3. DropCreateDatabaseAlways:此策略表示,每次运行程序都会重新创建数据库,这在开发和调试的时候非常有用。

4. 自定制数据库策略:可以自己实现IDatabaseInitializer来创建自己的策略。或者从已有的实现了IDatabaseInitializer接口的类派生。

如下示例显示了如何应用数据库创建策略:

public class  UserManContext : DbContext
{
    public UserManContext()
        : base("USMDBConnectionString")
    {
        Database.SetInitializer<UserManContext>(new CreateDatabaseIfNotExists<UserManContext>());
    }    
}

下面的代码创建了一个自定义策略,什么也没有做,但是我们可以在Seed方法里添加我们的种子数据。

public class  USMDBInitializer : DropCreateDatabaseAlways<UserManContext>
{
    protected override void Seed(UserManContext context)
    {
        base.Seed(context);
    }
}

虽然EF提供了在配置文件中配置策略的方法,如下所示:

<appSettings>
    <addkey="DatabaseInitializerForType EFCodeFirstSample.UserManContext, EFCodeFirstSample"
        value="System.Data.Entity.DropCreateDatabaseAlways`1[[EFCodeFirstSample.UserManContext,EFCodeFirstSample]], EntityFramework" />
  </appSettings>

Key必须以DatabaseInitializerForType开始,后边加空格,之后是context类的全名称,包括带命名空间的类名和所在的程序集名。Value是策略的全名称。可以看见key和value都非常难读,还不如自己写配置来的好。

如果不想使用策略,就可以关闭策略,特别是默认策略。关闭策略的代码如下:

public class  UserManContext : DbContext
{
    public UserManContext()
        : base("USMDBConnectionString")
    {           
        Database.SetInitializer<UserManContext>(null);
    } 
}

还可以在配置文件中关闭策略,如下:

<addkey="DatabaseInitializerForTypeEFCodeFirstSample.UserManContext, EFCodeFirstSample" value="Disabled" />

为数据库添加种子数据

上面提高可以在自定义数据库初始化策略中添加种子数据,下面的示例说明如何添加种子数据:

public class  USMDBInitializer : DropCreateDatabaseAlways<UserManContext>
{
    protected override void Seed(UserManContext context)
    {
        User admin =  new User();
        admin.Name = "admin";
        admin.DisplayName = "Administrator";
        admin.Status = 1;
        admin.LastModDate= DateTime.Now;
        context.Users.Add(admin);
        base.Seed(context);
    }
}

需要注意的是日期字段,数据库中的日期范围小于.NET中的日期范围,所以必须给一个合适的值,像DateTime.MinValue这样的值无法存储到数据库中。可以参考SqlDateTime类型来确定Sql数据库支持的时间范围。

移除约定

可以移除在System.Data.Entity.ModelConfiguration.Conventions 命名空间中定义的任何约定。下面的示例移除 PluralizingTableNameConvention。

publicclass  SchoolEntities: DbContext
{
  protected override voidOnModelCreating(DbModelBuilder modelBuilder)
  {
    // Configure CodeFirst to ignore PluralizingTableName convention
    // If you keepthis convention, the generated tables 
    // will havepluralized names.
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
  }
}

可插入约定

可插入(自定义)约定目前不受支持,正在针对 EF6 进行开发。