• 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);
    10 
    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.对象(表)的定义使用可以由各业务模块自行控制,只需要按照预先约定好,在注册的时候能够找到该类型即可。

  • 相关阅读:
    JVM学习笔记(一)------基本结构
    基于 Android 的 3D 视频样本代码
    Objective-C语法之代码块(block)的使用
    javabean总结
    oncopy和onpaste
    Linux/UNIX之信号(2)
    Html的空格显示
    硬盘的读写原理
    IntentFilter
    MyEclipse配置启动多个Tomcat
  • 原文地址:https://www.cnblogs.com/LittleJin/p/10582349.html
Copyright © 2020-2023  润新知