好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

EF实体对象解耦 - 泛型联表查询

为了达到模块间最小耦合,单模块业务数据不与其他模块发生关系。在操作数据库的时候,采用EF泛型操作。但泛型操作不好实现联表,经过一晚的试验发现了一种定义数据库上下文并联表的方式。


1.实体对象定义。实体对象可能存在于不同的业务模块中。他们之间是相互不知道对方存在的。

 1     public class User

 2     {

 3         [Key]

 4         [MaxLength(50)]

 5         public string userId { get; set; }

 6         [MaxLength(50)]

 7         public string userName { get; set; }

 8         public int age { get; set; }

 9         public string sex { get; set; }

10     }

11 

12     public class Order

13     {

14         [Key]

15         [MaxLength(50)]

16         public string orderId { get; set; }

17         public DateTime createTime { get; set; }

18         public string userId { get; set; }

19 

20         public string goodsId { get; set; }

21     }

22 

23     public class Goods

24     {

25         [Key]

26         [MaxLength(50)]

27         public string goodsId { get; set; }

28         public decimal price { get; set; }

29         public float weight { get; set; }

30     }

2.DbContext定义


 


  1     /// <summary>

  2     /// 基础的数据库操作类,

  3     /// 定义了所有的表结构,定义了数据迁移方案

  4     /// </summary>

  5     public class DbHelper : DbContext

  6     {

  7         static List<Type> tList;

  8 

  9         static DbHelper()

 10         {

 11             //也可以搜索所有程序集里面需要映射表的类型,这样就不需要外部传入了。

 12         }

 13 

 14         /// <summary>

 15         /// 初始化DB,该方法只需要被调用一次

 16         /// 总的说来,必须要在一开始就知道有哪些类型是要进行表映射的。(准确的说,只要在联表调用之前将对应类型在EF中注册过就可以。使用DbHelper<E>会将新的类型注册到EF,即便这个类型没有在此处统一注册★)

 17         /// </summary>

 18         /// <param name="eTypeList">需要关联的实体类对象</param>

 19         public static void InitDbHelper(List<Type> eTypeList=null)

 20         {

 21             tList = eTypeList ?? tList;

 22             using (DbHelper db = new Db.DbHelper())

 23             {

 24                 try

 25                 {

 26                     db.Set<string>().Add("");

 27                 }

 28                 catch (InvalidOperationException ex)

 29                 {

 30                 }

 31             }

 32 

 33         }

 34 

 35         public DbHelper() : base("defaultConnect")

 36         {

 37             System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbHelper, Configuration<DbHelper>>());

 38         }

 39 

 40         public DbHelper(string connectionName= "defaultConnect") : base(connectionName)

 41         {

 42             System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbHelper, Configuration<DbHelper>>());

 43         }

 44         protected override void OnModelCreating(DbModelBuilder modelBuilder)

 45         {

 46             if(tList != null)

 47             {

 48                 tList.ForEach(f=>{

 49                     modelBuilder.RegisterEntityType(f);

 50                 });

 51             }

 52             //modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

 53             base.OnModelCreating(modelBuilder);

 54         }

 55     }

 56 

 57     /// <summary>

 58     /// 数据迁移设置

 59     /// </summary>

 60     /// <typeparam name="T"></typeparam>

 61     public class Configuration<T> : DbMigrationsConfiguration<T> where T : DbContext

 62     {

 63         public Configuration()

 64         {

 65             AutomaticMigrationsEnabled = true; // 启用自动迁移功能

 66             AutomaticMigrationDataLossAllowed = true; // 允许自动删字段,危险但是不加这个不能重命名字段

 67         }

 68     }

 69     public class DbHelper<E> : DbContext where E : class

 70     {

 71         public DbHelper(string connectionName = "defaultConnect") : base(connectionName)

 72         {

 73         }

 74 

 75         private DbSet<E> Data { get; set; }

 76     }

 77     public class DbHelper<E1,E2>:DbContext where E1:class where E2:class

 78     {

 79         public DbHelper(string connectionName = "defaultConnect") : base(connectionName)

 80         {

 81         }

 82         

 83         private DbSet<E1> Data1{ get; set; }

 84         private DbSet<E2> Data2 { get; set; }

 85 

 86     }

 87 

 88     /// <summary>

 89     /// 如果超出了这里定义的实体个数,可以由外部自行定义DbHelper。

 90     /// </summary>

 91     /// <typeparam name="E1"></typeparam>

 92     /// <typeparam name="E2"></typeparam>

 93     /// <typeparam name="E3"></typeparam>

 94     public class DbHelper<E1,E2,E3> : DbContext where E1 : class where E2 : class where E3:class

 95     {

 96         public DbHelper(string connectionName = "defaultConnect") : base(connectionName)

 97         {

 98         }

 99 

100         private DbSet<E1> Data1 { get; set; }

101         private DbSet<E2> Data2 { get; set; }

102         private DbSet<E3> Data3 { get; set; }

103         

104     }

105 }

 


 


3.使用和操作。


在应用程序初始化的时候(如:Application_Start)执行一次。获取所有要注册的类型。


 1             List<Type> tList = new List<Type>();

 2             var ass = System.Reflection.Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "\\bin\\UserApi.dll");

 3 

 4             var uType = ass.GetType("UserApi.User");

 5             var gType = ass.GetType("UserApi.Goods");

 6             var oType = ass.GetType("UserApi.Order");

 7             tList.Add(uType);

 8             tList.Add(gType);

 9             tList.Add(oType);

11             DbHelper.InitDbHelper(tList);

以下是使用语句


//以下操作可能存在于不同的物业模块中

            using(DbHelper<User> db = new DbHelper<UserApi.User>())

            {

                db.Set<User>().Add(new UserApi.User { userId = "zxq", age = 18, userName = "zxq", sex="女" });

                db.SaveChanges();

            }

       //联三个表

            using(DbHelper<User, Order, Goods>  db = new DbHelper<UserApi.User, Order, Goods>())

            {

                var u = db.Set<User>();

                var o = db.Set<Order>();

                var g = db.Set<Goods>();


                var q = from uu in u

                        join oo in o

                        on uu.userId equals oo.userId

                        join gg in g

                        on oo.goodsId equals gg.goodsId

                        select new { uu, oo, gg };


                int count = q.Count();

            }

       //联两个表

            using (DbHelper<User,Order> db = new DbHelper<User, Order >())

            {

                db.Set<User>().Add(new UserApi.User

                {

                    userId = "fzj",

                    age = 18,

                    sex = "男",

                    userName = "fzj"

                });


                db.Set<Order>().Add(new Order

                {

                    createTime = DateTime.Now,

                    orderId = Guid.NewGuid().ToString("N"),

                    userId = "fzj"

                });


                db.SaveChanges();



                var u = db.Set<User>();

                var o = db.Set<Order>();


                var q = from uu in u

                        join oo in o

                        on uu.userId equals oo.userId

                        select new { uu, oo }; 


                foreach (var item in q)

                {

                    Console.WriteLine("age:{0} orderId:{1}",item.uu.age, item.oo.orderId);

                }

            }


总结:1.以上代码能够解决所有表映射对象必须集中定义的问题,同时解决使用泛型无法联表的问题。

        2.对象(表)的定义使用可以由各业务模块自行控制,只需要按照预先约定好,在注册的时候能够找到该类型即可。

转载于:https://www.cnblogs.com/LittleJin/p/10582349.html

查看更多关于EF实体对象解耦 - 泛型联表查询的详细内容...

  阅读:61次