zoukankan      html  css  js  c++  java
  • EF CodeFirst-----简单demo示例

          关于EF CodeFirst的文章院子里有很多的学习资料,但大多数都是一些讲Model通过特性或是Fluent API与数据库之间形成映射的关系,看了相关的文章之后,Model如何映射到数据还是有些迷糊,最近看了qouoww的这个系列文章http://www.cnblogs.com/qouoww/archive/2011/12/31/2309066.html,感觉不错,写下一个简单的demo作为总结,一起学习共勉。

          既然是采用CodeFirst的方式来编程的话,那么首先很明显一点我们得自己定义一个数据库上下文对象,如下所示:

     public class BaseDbContext<TContext> : DbContext
            where TContext : BaseDbContext<TContext>, new()
        {
            public BaseDbContext()
                : base("DefaultConnection")
            { 
                
            }
    }
    

      构造函数中引用的基类构造函数,如下所示:

            //     Constructs a new context instance using the given string as the name or connection
            //     string for the database to which a connection will be made.  See the class
            //     remarks for how this is used to create a connection.
            //
            // 参数:
            //   nameOrConnectionString:
            //     Either the database name or a connection string.
            [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
            public DbContext(string nameOrConnectionString);
    

       因此EF中默认的数据库连接字符串就是配置文件中默认的连接字符串:

        接下来我们我们创建一个数据库迁移配置类,这个类主要是用来封装由Model变化而引起的数据库结构的变化。如下所示:

     public sealed class TestConfiguration : DbMigrationsConfiguration<TestDbContext>
        {
            public TestConfiguration()
            {
                this.AutomaticMigrationsEnabled = true;
                this.AutomaticMigrationDataLossAllowed = true;
            }
    }
    

     这样我们就启动了迁移功能。紧接着我么来创建数据库迁移类来封装数据库迁移的相关方法,如下所示:

    [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestDatabaseMigrator), "MigrateDatabase")]
    namespace CodeFirst.Context
    {
        public class TestDatabaseMigrator
        {
            public static void MigrateDatabase()
            {
                DbMigrator dbMigrator = new DbMigrator(new TestConfiguration());
                dbMigrator.Update();
                using (TestDbContext dbContext = new TestDbContext())
                {
                    dbContext.Database.Initialize(true);
                }
            }
        }
    }
    

      我们可以看到DbMigrator类是以数据库迁移类作为参数实例化的, dbMigrator.Update()这句代码可以保证我们的目标数据库都是与Model映射成的最新的数据库结构。注意这一句话:

    [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestDatabaseMigrator), "MigrateDatabase")]
    

       WebActivator 允许您定义一个 PreApplicationStartMethod 属性,用于标记作为东西您获取 Web 应用程序启动时调用的方法,这样就可以保证先初始化我们的数据库。WebActivatorEx还有一个PostApplicationStartMethod方法,改方法是在全局的asax Application_Start 后调用的方法。

           TestDbContext的定义如下:

     public class TestDbContext : BaseDbContext<TestDbContext>
        {
            public DbSet<Test> MyTest { get; set; }
        }
    

      TestModel定义如下,用于与数据库映射成对应的表,请记住Model必须要有主键,否则会报错!

      public class Test
        {
            [Key]
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }
    

      我们启动web应用程序后,在vs中附带的数据库中可以看到EF创建的数据库:数据库名是与配置文件中的数据库名一致,而表名则是根据默认的约定生成的,即Model+s就是默认生成的表名。

         但是上面看起来很别扭,首先,数据库要生成到SqlServer中,那么我们修改下配置文件:

        <add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog= EF.CodeFirst;Integrated Security=True" providerName="System.Data.SqlClient" />

         然后我们想自己定义它生成的表名及相关的索引,注释之类的,那么我们首先要创建一个数据库初始化器:

     /// <summary>
        /// 数据库初始化器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class InitializerComposite<T>: IDatabaseInitializer<T>
            where T : DbContext
        {
            private readonly List<IDatabaseInitializer<T>> initializers;
    
            public InitializerComposite(params IDatabaseInitializer<T>[] databaseInitializers)
            {
                this.initializers = new List<IDatabaseInitializer<T>>();
                this.initializers.AddRange(databaseInitializers);
            }
    
            /// <summary>
            /// 执行数据库初始化器
            /// </summary>
            /// <param name="context"></param>
            public void InitializeDatabase(T context)
            {
                foreach (var initializer in this.initializers)
                {
                    initializer.InitializeDatabase(context);
                }
            }
        }

          同时我们需要修改下数据库上下文对象的基类,加入如下代码:

     /// <summary>
            /// 获取表的名字
            /// </summary>
            /// <param name="type"></param>
            /// <returns></returns>
            public virtual string GetTableName(Type type)
            {
                if (type == null)
                {
                    throw new ArgumentNullException("type");
                }
    
                string modelName = type.Name;
                return modelName;
            }
    
            /// <summary>
            /// </summary>
            /// <param name="modelBuilder"></param>
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                if (modelBuilder == null)
                {
                    throw new ArgumentNullException("modelBuilder");
                }
                // 定义表名规则
                modelBuilder.Entities().Configure(entity => entity.ToTable(this.GetTableName(entity.ClrType)));
                Database.SetInitializer(new InitializerComposite<TContext>());
            }

         表名直接就是利用Model的类名来生成,启动web程序,我们打开SqlServer,我们可以看到:数据库名在配置文件中指定,表名就是Model的类名Test,而不是默认的Tests。我们看下生成的表的结构:

    当然生成的字段的数据长度都是系统默认生成的长度,这个我们也可以修改,将在后面的文章中进行说明。

          但是有时候我们想在生成数据库的时候,同时有一些初始化的数据呢?这个时候我们就要在数据库迁移配置类中的Seed中加入一些初始数据:

     /// <summary>
            /// 对数据库中的进行相关的初始化操作
            /// </summary>
            /// <param name="context"></param>
            protected override void Seed(TestDbContext context)
            {
                var test1 = new Test() { Name="aa", Age=12 };
                var test2= new Test() { Name = "bb", Age = 12 };
                var test3 = new Test() { Name = "cc", Age = 12 };
                var tests = new List<Test> { test1, test2, test3};
                tests.ForEach(c => context.MyTest.AddOrUpdate(x => x.Name, c));
                context.SaveChanges();
                base.Seed(context);
            }

         我们再次打开数据库,可以发现,生成的表里面已经有了我们初始化的数据了:

        好了,EF CodeFirst的一些简单运用写到这里,日后将陆续更新。

  • 相关阅读:
    网站服务器架构设计
    使用同步或异步的方式完成 I/O 访问和操作(Windows核心编程)
    堆栈上的舞蹈之释放重引用(UAF) 漏洞原理实验分析
    内核模式下的线程同步的分析(Windows核心编程)
    用户模式下的线程同步的分析(Windows核心编程)
    Linux下部署Django项目
    HDU 2075 A|B?
    HDU 2052 Picture
    HDU 2024 C语言合法标识符
    HDU 2026 首字母变大写
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/3141439.html
Copyright © 2011-2022 走看看