EF实体对象解耦 - 泛型联表查询
为了达到模块间最小耦合,单模块业务数据不与其他模块发生关系。在操作数据库的时候,采用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实体对象解耦 - 泛型联表查询的更多相关文章
- MyBatis联表查询
MyBatis逆向工程主要用于单表操作,那么需要进行联表操作时,往往需要我们自己去写sql语句. 写sql语句之前,我们先修改一下实体类 Course.java: public class Cours ...
- Spring Hibernate JPA 联表查询 复杂查询(转)
今天刷网,才发现: 1)如果想用hibernate注解,是不是一定会用到jpa的? 是.如果hibernate认为jpa的注解够用,就直接用.否则会弄一个自己的出来作为补充. 2)jpa和hibern ...
- Spring Hibernate JPA 联表查询 复杂查询
今天刷网,才发现: 1)如果想用hibernate注解,是不是一定会用到jpa的? 是.如果hibernate认为jpa的注解够用,就直接用.否则会弄一个自己的出来作为补充. 2)jpa和hibern ...
- mybatis 联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- MyBatis-Plus联表查询的短板,终于有一款工具补齐了
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. mybatis-plus作为mybatis的增强工具,它的出现极大的简化了开发中的数据库操作,但是长久以来,它的 ...
- .NET 6 跨服务器联表查询
一.大家是否有这个需求 1.跨品种查询 :比如 MYSQL和一个SQLSERVER进行联表查询 ,或者SQLITE和MYSQL进行联表查询 2.跨服务器查询 : A服务器和B服务器查询 如果想同时支持 ...
- Django之model联表:一对多、跨表操作,联表查询
表结构概述 model.py : class Something(models.Model): name = models.CharField(max_length=32) class UserTyp ...
- FreeSql (十七)联表查询
FreeSql在查询数据下足了功能,链式查询语法.多表查询.表达式函数支持得非常到位. IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnect ...
- Mybatis框架-联表查询显示问题解决
需求:查询结果要求显示用户名,用户密码,用户的角色 因为在用户表中只有用户角色码值,没有对应的名称,角色名称是在码表smbms_role表中,这时我们就需要联表查询了. 这里需要在User实体类中添加 ...
随机推荐
- 开发工具 -- PyDev的使用
1.创建PyDev工程 2.创建源文件夹src 3.新建.py文件 其他注意事项 1.设置字体大小 2.显示行号Ctrl + F10 3.编码设置为UTF-8 4.最好将工程创建到默认工作空间 5.总 ...
- centos6.5 + 7 静态ip配置
2017/09/19日更, centos6.5 可用 DEVICE=eth0 TYPE=Ethernet ONBOOT=yes NM_CONTROLLED=yes BOOTPROTO=static D ...
- python迭代器、生成器、装饰器
1 迭代器 这里我们先来回顾一下什么是可迭代对象(Iterable)? 可以直接作用于for循环的对象统称为可迭代对象,即Iterable. # 一是集合数据类型,如list.tuple.dict.s ...
- SpringMVC源码阅读:视图解析器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- Ubuntu18.0.4查看显示器型号
在官网https://launchpad.net/ubuntu/+source/xresprobe下载二进制包,apt-get目前无法安装xresprobe 输入命令sudo ddcprobe 得到如 ...
- JAVA项目将 Oracle 转 MySQL 数据库转换(Hibernate 持久层)
项目开发时用的是Oracle数据库,但为了更好的做分布式,做集群,我们要将数据库转成 MySQL! 在数据库迁移中首先要做的事是将 Oracle 的表结构以及数据 克隆到 MySQL 数据库. 这点不 ...
- 合天misc100
打开txt文件是一串RGB颜色值 用len(file.readlines()),发现颜色值有61366个,能分解成122*503 from PIL import Image length = 122 ...
- SqlServer入门学习
--distinct(去除重复数据)select distinct Time from HightTable--Between select * from HightTable where ID BE ...
- [整理]EF6.X更新了什么(版本历史中文版)
下定决心以后用EF6.x版本了.想看看有什么更新特性,结果去人家github老巢一看,EF7 for vnext,顿时蛋疼了起来.想想国内这种技术氛围,有多少还在用ASP的,有多少还在用ADO.NET ...
- fzu 2163
Problem 2163 多米诺骨牌 Accept: 17 Submit: 50Time Limit: 1000 mSec Memory Limit : 32768 KB Problem ...