黑基网 首页 学院 电脑技术 查看内容

EF 的 霸气配置 秒杀一切

2014-10-27 10:48| 投稿: computer

摘要:  通过EF 作为操作数据库的工具有一段时间了,也做了几个相对不大的项目,慢慢的也对EF的使用摸索出来了一些规则,虽然说不是技术难点,但是,我说的是但是,能够提高我们开发效率的棉花糖有时我们还...
 通过EF 作为操作数据库的工具有一段时间了,也做了几个相对不大的项目,慢慢的也对EF的使用摸索出来了一些规则,虽然说不是技术难点,但是,我说的是但是,能够提高我们开发效率的棉花糖有时我们还是必须要吃的,因为他确实很甜很甜。现在Ef已经更新到6.1.1了,从原来的5.0 到现在也不过是短短的一年多,所以说Ef的生命力还是很强的。什么 你要我对比一下EF和NHibernate的优缺点,这不是本文的重点,我只说一句,EF侧重代码配置,NHibernate 侧重配置文件配置,但是说哪种好,萝卜白菜 各有所爱吧。  刚开始使用EF操作数据表我们是这样使用的,通过在DBContext中添加Dbset<T> 这种形式的属性来实现,但是,我说的是但是,这种方式随着我们的实体Domain越来越多的时候我们不得不一个一个的添加到DbContext中,这不禁让我很苦恼,有没有更好的办法呢? 为了说明的方便,我建立了一个控制台的程序,毕竟EF和具体的项目类型无关。 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 TestContext testContext = new TestContext(); 6 ///获取数据库表Person中的所有数据 在查询的时候最好加上AsNoTracking 禁止EF跟踪 7 var personList = testContext.Persons.AsNoTracking().ToList(); 8 } 9 } 10 11 public class TestContext : DbContext 12 { 13 private static TestContext _instance; 14 15 public static TestContext Instance 16 { 17 get 18 { 19 if (_instance == null) 20 { 21 _instance = new TestContext(); 22 } 23 return _instance; 24 } 25 } 26 27 private string _connectionString; 28 29 public string ConnectionString 30 { 31 get 32 { 33 if (string.IsNullOrWhiteSpace(_connectionString)) 34 { 35 _connectionString = ConfigurationManager.ConnectionStrings["testConn"].ConnectionString; 36 } 37 return _connectionString; 38 } 39 set 40 { 41 _connectionString = value; 42 } 43 } 44 45 public TestContext() 46 : base("name=testConn") 47 { 48 _connectionString = ConfigurationManager.ConnectionStrings["testConn"].ConnectionString; 49 } 50 public TestContext(string connectionString) 51 : base(connectionString) 52 { 53 54 } 55 56 /// <summary> 57 /// 定义的实体 58 /// </summary> 59 public DbSet<Person> Persons { get; set; } 60 } 61 [Table("Person")] 62 public class Person 63 { 64 public string Name { get; set; } 65 66 public string Age { get; set; } 67 }  每次添加实体Domain 都要在DbContext 中添加一个对应的属性,很令人苦恼,并且如果属性为string 类型,在数据库中创建的表的长度为max,当然我们可以修改EF的默认约定来让string 类型在数据表中具有一定的长度。我们有没有更好的方式来控制EF创建的数据表呢,并且要易于维护,让所有同事都可以很轻松的掌握。当然,有一个新大陆被发现了。我们通过反射来找到所有继承自EntityTypeConfiguration的类,这些类就是EF的映射类,我们把这些映射类添加到EF  configuration中就可以实现我们的功能,说太多,上代码。 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 TestContext testContext = new TestContext(); 6 ///获取数据库表Person中的所有数据 在查询的时候最好加上AsNoTracking 禁止EF跟踪 7 // var personList = testContext.Persons.AsNoTracking().ToList(); 8 } 9 } 10 11 public class TestContext : DbContext 12 { 13 private static TestContext _instance; 14 15 public static TestContext Instance 16 { 17 get 18 { 19 if (_instance == null) 20 { 21 _instance = new TestContext(); 22 } 23 return _instance; 24 } 25 } 26 27 private string _connectionString; 28 29 public string ConnectionString 30 { 31 get 32 { 33 if (string.IsNullOrWhiteSpace(_connectionString)) 34 { 35 _connectionString = ConfigurationManager.ConnectionStrings["testConn"].ConnectionString; 36 } 37 return _connectionString; 38 } 39 set 40 { 41 _connectionString = value; 42 } 43 } 44 45 public TestContext() 46 : base("name=testConn") 47 { 48 _connectionString = ConfigurationManager.ConnectionStrings["testConn"].ConnectionString; 49 } 50 public TestContext(string connectionString) 51 : base(connectionString) 52 { 53 54 } 55 protected override void OnModelCreating(DbModelBuilder modelBuilder) 56 { 57 ///DomainMapping 所在的程序集一定要写对,因为目前在当前项目所以是采用的当前正在运行的程序集 如果你的mapping在单独的项目中 记得要加载对应的assembly 58 ///这是重点 59 var typesToRegister = Assembly.GetExecutingAssembly().GetTypes() 60 .Where(type => !String.IsNullOrEmpty(type.Namespace)) 61 .Where(type => type.BaseType != null && type.BaseType.BaseType != null && type.BaseType.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)); 62 foreach (var type in typesToRegister) 63 { 64 dynamic configurationInstance = Activator.CreateInstance(type); 65 modelBuilder.Configurations.Add(configurationInstance); 66 } 67 68 base.OnModelCreating(modelBuilder); 69 } 70 71 72 } 73 74 public class BaseDomain 75 { 76 77 } 78 [Table("Person")] 79 public class Person 80 { 81 public string ID { get; set; } 82 public string Name { get; set; } 83 84 public string Age { get; set; } 85 } 86 87 public class PersonMapping : BaseDomainMapping<Person> 88 { 89 public override void Init() 90 { 91 this.ToTable("Person"); 92 this.HasKey(l => l.ID); 93 this.Property(l => l.Name).HasMaxLength(200).IsRequired();//设置Name属性长度为200 并且是必填 94 this.Property(l => l.Age).HasMaxLength(200).IsOptional(); //设置Age长度为200 并且可为空 95 } 96 } 97 98 99 public abstract class BaseDomainMapping<T> : EntityTypeConfiguration<T> 100 where T : BaseDomain, new() 101 { 102 103 public BaseDomainMapping() 104 { 105 Init(); 106 } 107 /// <summary> 108 /// 初始化代码 109 /// </summary> 110 public virtual void Init() 111 { 112 Console.WriteLine("Init"); 113 } 114 } 这个其实用到了主要两个知识点,一个就是抽象类中定义的virtual方法,在抽象类中进行调用,在继承自抽象类的类中override这个方法,此文为Init,那么子类中的这个方法也会被调用,避免在每个子类中都要写调用Init的方法。 第二个就是,注意OnModelCreating  方法,他找到所有继承自EntityTypeConfiguration的类,然后添加到Configuration中,也就是我们实现了多个配置,统一添加到EF的配置中,EF在执行的时候会执行所有的配置类,当然包括我们自己定义的映射Mapping。大家可能要说了,这样是可以只写一个映射类就可以,但是我们怎么访问呢?没有了原来的通过属性 TestContext testContext = new TestContext(); ///获取数据库表Person中的所有数据 在查询的时候最好加上AsNoTracking 禁止EF跟踪 var personList = testContext.Persons.AsNoTracking().ToList(); 通过属性访问很简单方便,我们需要想办法获取到DbSet 类通过EF访问数据库,现在我们的思路就是通过我们定义的TestContext ,找到我们通过反射注册的所有配置类。 1 /// <summary> 2 /// Entity Framework repository 3 /// </summary>
小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论


新出炉

返回顶部