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定义

   //这个对象只是为了注册类型到EF,需要在调用所有数据库语句之前执行一次就够了,具体实现就看设计了。
public class DbHelper : DbContext { public DbHelper() : base("defaultConnect") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) {
       //这里通过程序集,实现所有数据库表类型查找。
var ass = System.Reflection.Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "\\bin\\UserApi.dll");        //根据自己定义的规则,找到所有需要注册的表。 var uType = ass.GetType("UserApi.User"); var gType = ass.GetType("UserApi.Goods"); var oType = ass.GetType("UserApi.Order"); //执行注册。 modelBuilder.RegisterEntityType(uType); modelBuilder.RegisterEntityType(gType); modelBuilder.RegisterEntityType(oType); //modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); base.OnModelCreating(modelBuilder); } }
//定义带一个参数的情况
public class DbHelper<E> : DbContext where E : class { public DbHelper() : base("defaultConnect") { } //用Data调不直观,使用 var u = db.Set<User>();这种形式不易混淆,特别是参数多的情况 internal DbSet<E> Data { get; set; } }
//定义两个表连接情况
public class DbHelper<E1,E2>:DbContext where E1:class where E2:class { public DbHelper() : base("defaultConnect") { } internal DbSet<E1> Data1{ get; set; } internal DbSet<E2> Data2 { get; set; } }
   //定义三个表连接情况
public class DbHelper<E1, E2,E3> : DbContext where E1 : class where E2 : class where E3:class { public DbHelper() : base("defaultConnect") { } internal DbSet<E1> Data1 { get; set; } internal DbSet<E2> Data2 { get; set; } internal DbSet<E3> Data3 { get; set; } }

//N个表连接情况。。。。。

3.使用和操作。

            //必须执行一次该语句,这个语句只要在调用数据库之前执行一次就够了,具体什么时候执行就看设计者了
            using (DbHelper db = new DbHelper())
            {
                try
                {
                    //实际添加数据不会成功,但在这里将创建所有表。
                    db.Set<User>().Add(new UserApi.User { });
                }
                catch(Exception ex)
                {
                    //上面执行肯定会抛出异常
                }
            }

            //以下操作可能存在于不同的物业模块中
            using(DbHelper<User> db = new DbHelper<UserApi.User>())
            {
                db.Set<User>().Add(new UserApi.User { userId = "zxq", age = 31, 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.对象(表)的定义使用可以由各业务模块自行控制,只需要按照预先约定好,在注册的时候能够找到该类型即可。

猜你喜欢

转载自www.cnblogs.com/LittleJin/p/10582349.html