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实体类中添加 ...
随机推荐
- 《垃圾回收的算法与实现》——保守式GC
保守式GC 保守式GC指"不能识别指针和非指针的GC". 不明确的根,寄存器.调用栈.全局变量空间等属于GC root,这些GC均不能识别出是指针还是非指针. 指针的识别,在不明确 ...
- es6中let,const区别与其用法
ECMAScript 是什么? 首先,我们都知道JavaScript由三部分组成:ECMAScript,DOM,BOM: 其中的ECMAScript是Javascript的语法规范. ECMAScri ...
- Word2vec 理解
1.有DNN做的word2vec,取隐藏层到softmax层的权重为词向量,softmax层的叶子节点数为词汇表大小 2-3的最开始的词向量是随机初始化的 2.哈夫曼树:左边走 sigmoid(当前节 ...
- Memcached理解笔2---XMemcached&Spring集成
一.Memcached Client简要介绍 Memcached Client目前有3种: Memcached Client for Java SpyMemcached XMemcached 这三种C ...
- python总结--目录(转)
python模块 [Python]随机数与随机字符串 举例说明Python的CSV模块 python模块之smtplib: 用python发送SSL/TLS安全邮件 python模块之e ...
- ABP实战--修改语言配置XML至Json
从ABP官网下载的Zero的多语言配置默认是使用XML文件的,实际使用中XML是没有Json简洁明了的,所以我们将其修改为Json格式. 修改MyLocalizationConfigurer.cs文件 ...
- ruby字符串连接
malls = Mall.allcount = 0malls.each do |mall| count += 1 if mall.parent_ids[0] province ...
- bzoj 2138: stone
Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆 包含Ai颗石子.每1分钟,Nan会在编号在[Li,Ri]之间的石 ...
- c#Image.FromFile图形加载异常处理
public void UpdateImg(string picpath) { //更新至控件中 PnlImageShow.BackgroundImage = LoadImgPath(picpath) ...
- C# 数据库增加新表怎么更新ef
找到dbmx文件,打开,右键,更新模型 也可以 右键从模型中删除 重新更新过来,感觉说了句废话 哈哈