EFCore 和 FreeSql 都是 ORM,在各自领域都有着独特的优势。

问题起源

假设某项目是使用 EFCore 开发的,且实体 特性或FluentApi 都配置好了,如:

protected override void MapTable( EntityTypeBuilder builder ) {
builder.ToTable( "cg_kssqbs" ); //实体表名有单独定义
}

此时用 FreeSql 操作实体会报错:数据库表不存在。除非又配置一套FreeSql的 特性或FluentApi,这显然会比较麻烦。

问:为什么不统一,非要各自定义标准?

答:每个 ORM 的理念不同,提供的功能也不尽相同,FreeSql 的理念是“打造 .NETCore 最方便的 ORM”。与 EFCore 相比只提供了极少的特性配置(如:主键、自增、类型、别名、可空),并且这些设定针对已现实的数据库都是一致的。因此 FreeSql 有单独一套简单的实体配置语法,特别声明:方便、简单指的是上手简单,并非说 FreeSql 功能简单。

来自 Issues 4 《建议能结合EF Core的一些特性来弄 #4》

解决方法

1、关闭 FreeSql 迁移功能

IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10")
//.UseAutoSyncStructure(true) //自动同步实体结构到数据库,这行一定要关闭
.Build();

原因是 EFCore 与 FreeSql 迁移会发生冲突,那边迁移好了,这边又迁移的逻辑显然不对。

2、读取 EFCore 的实体配置数据

ICodeFirst.ConfigEntity 方法可以在程序运行中配置,从而改变实体的映射

以扩展类库的方式现实需求代码如下:

public static void ConfigEntity(this ICodeFirst codeFirst, IModel efmodel) {

    foreach (var type in efmodel.GetEntityTypes()) {

        codeFirst.ConfigEntity(type.ClrType, a => {

            //表名
var relationalTableName = type.FindAnnotation("Relational:TableName");
if (relationalTableName != null)
a.Name(relationalTableName.Value?.ToString() ?? type.ClrType.Name); foreach (var prop in type.GetProperties()) { var freeProp = a.Property(prop.Name); //列名
var relationalColumnName = prop.FindAnnotation("Relational:ColumnName");
if (relationalColumnName != null)
freeProp.Name(relationalColumnName.Value?.ToString() ?? prop.Name); //主键
freeProp.IsPrimary(prop.IsPrimaryKey()); //自增
freeProp.IsIdentity(
prop.ValueGenerated == ValueGenerated.Never ||
prop.ValueGenerated == ValueGenerated.OnAdd ||
prop.GetAnnotations().Where(z =>
z.Name == "SqlServer:ValueGenerationStrategy" && z.Value.ToString().Contains("IdentityColumn") //sqlserver 自增
|| z.Value.ToString().Contains("IdentityColumn") //其他数据库实现未经测试
).Any()
); //可空
freeProp.IsNullable(prop.AfterSaveBehavior != PropertySaveBehavior.Throw); //类型
var relationalColumnType = prop.FindAnnotation("Relational:ColumnType");
if (relationalColumnType != null) { var dbType = relationalColumnType.ToString();
if (!string.IsNullOrEmpty(dbType)) { var maxLength = prop.FindAnnotation("MaxLength");
if (maxLength != null)
dbType += $"({maxLength})"; freeProp.DbType(dbType);
}
}
}
});
}
}

测试

public class Song {
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
} public class SongContext : DbContext { public DbSet<Song> Songs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlite(@"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10");
}
} Console.WriteLine(fsql.Insert<Song>().AppendData(new Song()).ToSql());
//INSERT INTO "Song"("Id", "Title") VALUES(@Id0, @Title0) using (var sdb = new SongContext()) {
Fsql.CodeFirst.ConfigEntity(sdb.Model);
//ps: 只需要配置一次
} Console.WriteLine(fsql.Insert<Song>().AppendData(new Song()).ToSql());
"INSERT INTO "Songs"("Title") VALUES(@Title0)"
//此处配置已生效,Id 为自增时不插入,表名也改名了 Songs

示范项目已整理上传到 Github/Examples/efcore_to_freesql

有几个问题

本人对 EF 不太熟,有几个问题请教:

1、EFCore 是不是非要定义 DBContext 来使用?

2、Microsoft.EntityFrameworkCore.Metadata.IModel 有没有变化通知或拦截的方法?简化配置;

3、EFCore 自增各种数据库的现实貌似有差异?

结束语

感谢观看,以上是我的解决思路,如果有更好的建议或方法欢迎讨论。

FreeSql 虽然目前的版本发布为 0.xx,但功能和可能性已经较高了。

Github:https://github.com/2881099/FreeSql

Wiki:https://github.com/2881099/FreeSql/wiki

在 EFCore 定义的实体中进行 FreeSql 开发的更多相关文章

  1. 【mybatis】mybatis使用java实体中定义的常量,或静态方法

    mybatis使用java实体中定义的常量 示例代码: <select id="findDealerInfo" parameterType="com.pisen.c ...

  2. Java定义bean实体类中的变量时变量名的问题

    首先:TMD,这个问题花了我两个多小时,居然是因为一个字母的大小写导致的,我瞬间就&Y^%^&%&()*%¥%¥¥&^#@%&; 事情是酱紫的: 我定义了一个变 ...

  3. Nutz Dao实体中索引注解的使用(@TableIndexes@Index)

    Nutz是一组轻便小型的框架的集合, 各个部分可以被独立使用,把SSH的精华封装在一个1M左右的jar包中,Nutz不对其他任何第三方库产生依赖,如果不考虑数据库链接和日志的话,创建完美的Web应用只 ...

  4. JavaBean定义、JSP中使用以及内省操作

        Apache commons 一系列的开源工具室非常值得学习的实现. 一 JavaBean定义     JavaBean是一种可重复使用.且跨平台的软件组件.JavaBean可分为两种:一种是 ...

  5. Drupal 自己定义主题实体 Theming Custom Entities

    在自己定义主题中输出结果时,有三个部分或很多其它特殊的函数.如 hook_menu,Page Callback.MODULE_theme 钩子 1.hook_menu 为了使用自己定义的实体.像创建. ...

  6. EFCore:关于DDD中值对象(Owns)无法更新数值

    最近使用DDD+EFCore时,使用EFCore提供的OwnsOne或者OwnsMany关联值对象保存数据,没想到遇到一个很奇怪的问题:值对象中的值竟然无法被EFCore保存!也没有抛出任何异常!我瞬 ...

  7. MongoDB学习笔记~MongoDB实体中的值对象

    回到目录 注意,这里说的值对象是指在MongoDB实体类中的,并不是DDD中的值对象,不过,两者也是联系,就是它是对类的补充,自己本身没有存在的价值,而在值对象中,也是不需要有主键Id的,这与DDD也 ...

  8. entity.Student@150f3932, entity.Student@1a740c6b 没有实体中的数据

    public class AppServerAction extends BaseAction {    /**     *      */ /**      * 初始化 “我的产品”列表 JSP页面 ...

  9. petapoco 实体中字段去掉关联(类似于EF中的NotMap)

    怎么才能让不是数据库表中的字段放在实体中而不影响正常的插入和更新呢? 找到 PetaPoco.cs 文件,打开之后,搜索插入方法(Insert),然后继续找到下一层方法 就能看到如下代码: 看到这个注 ...

随机推荐

  1. UE4笔记:利用Widget设计一个切换材质功能

    UE4引擎中的Widget蓝图是一个重要的工具,可用于场景中的页面叠加,镜头绑定,场景切换等多处地方,在这里笔者介绍一种利用控件蓝图和场景中物体进行信息交互的方法,直观的体现就是进行物体的材质切换. ...

  2. RabbitMQ windows安装(一 )

    RabbitMQ 简单介绍: 是可以实现应用程序的解耦和异步,也可用作消息缓冲和消息分发的消息队列(MQ): 安装: 1.安装RabbitMQ前先安装Erlang语言开发包,下载地址:http://w ...

  3. 深入理解css3中的线性渐变

    css3中的线性渐变 线性渐变公式: background-image: linear-gradient( [ <angle> | <side-or-corner> ]?, & ...

  4. Django rest framework(7)----分页

    目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...

  5. @EnableTransactionManagement注解理解

    @EnableTransactionManagement表示开启事务支持,在springboot项目中一般配置在启动类上,效果等同于xml配置的<tx:annotation-driven /&g ...

  6. SSM-Spring-20:Spring中事务基础

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 事务 事务是什么? 我记得当初的百度百科上讲,事务是执行的最小逻辑单元,它们要么都执行,要么都不执行 (同生共 ...

  7. linux编译安装时常见错误解决办法

    This article is post on https://coderwall.com/p/ggmpfa 原文链接:http://www.bkjia.com/PHPjc/1008013.html ...

  8. VMware 非简易安装centos6(静态ip配置)

    1.选择新建虚拟机 在弹出框中我选择推荐安装 然后点击下一步 2.选择稍后安装操作系统(不然会默认简易安装) 接着一直下一步就可以了,最后到这个页面 4.如下图选择事先下载好的安装文件 5.配置桥接模 ...

  9. CSS选择器详细总结

    一.基本选择器 序号 选择器 含义 1. * 通用元素选择器,匹配任何元素 2. E 标签选择器,匹配所有使用E标签的元素 3. .info class选择器,匹配所有class属性中包含info的元 ...

  10. vue.js小总结

    Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统; 指令带有前缀 v-,以表示它们是 Vue 提供的特殊特性; v-for 指令可以绑定数组的数据来渲染一个项目列 ...