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

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

     public class User
{
[Key]
[MaxLength()]
public string userId { get; set; }
[MaxLength()]
public string userName { get; set; }
public int age { get; set; }
public string sex { get; set; }
} public class Order
{
[Key]
[MaxLength()]
public string orderId { get; set; }
public DateTime createTime { get; set; }
public string userId { get; set; } public string goodsId { get; set; }
} public class Goods
{
[Key]
[MaxLength()]
public string goodsId { get; set; }
public decimal price { get; set; }
public float weight { get; set; }
}

2.DbContext定义

     /// <summary>
/// 基础的数据库操作类,
/// 定义了所有的表结构,定义了数据迁移方案
/// </summary>
public class DbHelper : DbContext
{
static List<Type> tList; static DbHelper()
{
//也可以搜索所有程序集里面需要映射表的类型,这样就不需要外部传入了。
} /// <summary>
/// 初始化DB,该方法只需要被调用一次
/// 总的说来,必须要在一开始就知道有哪些类型是要进行表映射的。(准确的说,只要在联表调用之前将对应类型在EF中注册过就可以。使用DbHelper<E>会将新的类型注册到EF,即便这个类型没有在此处统一注册★)
/// </summary>
/// <param name="eTypeList">需要关联的实体类对象</param>
public static void InitDbHelper(List<Type> eTypeList=null)
{
tList = eTypeList ?? tList;
using (DbHelper db = new Db.DbHelper())
{
try
{
db.Set<string>().Add("");
}
catch (InvalidOperationException ex)
{
}
} } public DbHelper() : base("defaultConnect")
{
System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbHelper, Configuration<DbHelper>>());
} public DbHelper(string connectionName= "defaultConnect") : base(connectionName)
{
System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbHelper, Configuration<DbHelper>>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if(tList != null)
{
tList.ForEach(f=>{
modelBuilder.RegisterEntityType(f);
});
}
//modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
} /// <summary>
/// 数据迁移设置
/// </summary>
/// <typeparam name="T"></typeparam>
public class Configuration<T> : DbMigrationsConfiguration<T> where T : DbContext
{
public Configuration()
{
AutomaticMigrationsEnabled = true; // 启用自动迁移功能
AutomaticMigrationDataLossAllowed = true; // 允许自动删字段,危险但是不加这个不能重命名字段
}
}
public class DbHelper<E> : DbContext where E : class
{
public DbHelper(string connectionName = "defaultConnect") : base(connectionName)
{
} private DbSet<E> Data { get; set; }
}
public class DbHelper<E1,E2>:DbContext where E1:class where E2:class
{
public DbHelper(string connectionName = "defaultConnect") : base(connectionName)
{
} private DbSet<E1> Data1{ get; set; }
private DbSet<E2> Data2 { get; set; } } /// <summary>
/// 如果超出了这里定义的实体个数,可以由外部自行定义DbHelper。
/// </summary>
/// <typeparam name="E1"></typeparam>
/// <typeparam name="E2"></typeparam>
/// <typeparam name="E3"></typeparam>
public class DbHelper<E1,E2,E3> : DbContext where E1 : class where E2 : class where E3:class
{
public DbHelper(string connectionName = "defaultConnect") : base(connectionName)
{
} private DbSet<E1> Data1 { get; set; }
private DbSet<E2> Data2 { get; set; }
private DbSet<E3> Data3 { get; set; } }
}

3.使用和操作。

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

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

EF实体对象解耦 - 泛型联表查询的更多相关文章

  1. MyBatis联表查询

    MyBatis逆向工程主要用于单表操作,那么需要进行联表操作时,往往需要我们自己去写sql语句. 写sql语句之前,我们先修改一下实体类 Course.java: public class Cours ...

  2. Spring Hibernate JPA 联表查询 复杂查询(转)

    今天刷网,才发现: 1)如果想用hibernate注解,是不是一定会用到jpa的? 是.如果hibernate认为jpa的注解够用,就直接用.否则会弄一个自己的出来作为补充. 2)jpa和hibern ...

  3. Spring Hibernate JPA 联表查询 复杂查询

    今天刷网,才发现: 1)如果想用hibernate注解,是不是一定会用到jpa的? 是.如果hibernate认为jpa的注解够用,就直接用.否则会弄一个自己的出来作为补充. 2)jpa和hibern ...

  4. mybatis 联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  5. MyBatis-Plus联表查询的短板,终于有一款工具补齐了

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. mybatis-plus作为mybatis的增强工具,它的出现极大的简化了开发中的数据库操作,但是长久以来,它的 ...

  6. .NET 6 跨服务器联表查询

    一.大家是否有这个需求 1.跨品种查询 :比如 MYSQL和一个SQLSERVER进行联表查询 ,或者SQLITE和MYSQL进行联表查询 2.跨服务器查询 : A服务器和B服务器查询 如果想同时支持 ...

  7. Django之model联表:一对多、跨表操作,联表查询

    表结构概述 model.py : class Something(models.Model): name = models.CharField(max_length=32) class UserTyp ...

  8. FreeSql (十七)联表查询

    FreeSql在查询数据下足了功能,链式查询语法.多表查询.表达式函数支持得非常到位. IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnect ...

  9. Mybatis框架-联表查询显示问题解决

    需求:查询结果要求显示用户名,用户密码,用户的角色 因为在用户表中只有用户角色码值,没有对应的名称,角色名称是在码表smbms_role表中,这时我们就需要联表查询了. 这里需要在User实体类中添加 ...

随机推荐

  1. Android4.0 Launcher 源码分析1——Launcher整体结构

    1.Launcher整体结构 桌面程序其实并不包含桌面壁纸,桌面壁纸其实是由 WallpaperManagerService来提供,整个桌面其实是叠加在整个桌面壁纸上的另外一个层. 1.1 WorkS ...

  2. django项目的生产环境部署,利用nginx+uwsgi

    1.坏境准备 centos6.5 django项目 python坏境(python3.6,) 所需的各种模块(django,uwsgi,sqlite3)具体看坏境 我的测试django项目的数据库用的 ...

  3. 修改salt-minion的id后报错解决方法

    centos7使用命令 /usr/bin/salt-minion start运行报错 Error parsing configuration file: /etc/salt/master - expe ...

  4. 开发小技巧1——Logger

    开发小技巧1——Logger 在项目中加入静态Logger类,用于捕获并记录程序的进度.错误信息:   public static class Logger { public static void ...

  5. log4配置

    log4j 和 log4j2 方式一:log4j2.xml 添加 jar 包 <!-- log4j-core --> <!-- <dependency> <grou ...

  6. CUBA 7:崭新的篇章

    原文链接:https://www.cuba-platform.com/blog/cuba-7-the-new-chapter 最近(2019年春节前夕)发布的 CUBA 和 Studio 的第7个版本 ...

  7. Border属性的各种变化

    本文前部分转自http://www.cnblogs.com/binyong/archive/2009/02/21/1395386.html,但是文章并未解释实现的原理,因此,后面本文也对次进行了解释. ...

  8. AOE网与AOV网

    因为有人无端怀疑此博客为抄袭, 且作者写作此博客时仅为应试之用,今毕业已久此文章已无用处 故删除文章,不想再无故受到打扰 祝好

  9. Docker 私有registry出现的证书问题

    在上一篇 最近搭建的私有registry里,参考的文章指出,在push时可能出现问题: 可能会出现无法push镜像到私有仓库的问题.这是因为我们启动的registry服务不是安全可信赖的.这是我们需要 ...

  10. C# 开发者审查代码的41条建议

    1. 确保没有任何警告(warnings). 2.如果先执行Code Analysis(启用所有Microsoft Rules)再消除所有警告就更好了. 3. 去掉所有没有用到的usings.编码过程 ...