Giter Site home page Giter Site logo

dotnetcore / freesql Goto Github PK

View Code? Open in Web Editor NEW
4.0K 150.0 838.0 20.73 MB

🦄 .NET aot orm, C# orm, VB.NET orm, Mysql orm, Postgresql orm, SqlServer orm, Oracle orm, Sqlite orm, Firebird orm, 达梦 orm, 人大金仓 orm, 神通 orm, 翰高 orm, 南大通用 orm, 虚谷 orm, 国产 orm, Clickhouse orm, QuestDB orm, MsAccess orm.

Home Page: http://freesql.net

License: MIT License

C# 99.96% Smalltalk 0.01% Visual Basic .NET 0.04%
orm codefirst mysql sqlite sqlserver postgresql odbc dameng kingbase access

freesql's Introduction

🦄 FreeSql, The first AOT ORM!

FreeSql is a powerful O/RM component, supports .NET Core 2.1+, .NET Framework 4.0+, Xamarin, And AOT.

Member project of .NET Core Community nuget stats GitHub license

English | 中文

  • 🛠 Support CodeFirst data migration.
  • 💻 Support DbFirst import entity class from database, or use Generation Tool.
  • ⛳ Support advanced type mapping, such as PostgreSQL array type, etc.
  • 🌲 Support expression functions, and customizable analysis.
  • 🏁 Support one-to-many and many-to-many navigation properties, include and lazy loading.
  • 📃 Support Read/Write separation, Splitting Table/Database, Global filters, Optimistic and pessimistic locker.
  • 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/ClickHouse/QuestDB/MsAccess, etc.

QQ Groups:561616019(available)、4336577(full)、8578575(full)、52508226(full)

📚 Documentation

Get started  |  Select  |  Update  |  Insert  |  Delete  |  FAQ  
Expression  |  CodeFirst  |  DbFirst  |  Filters  |  AOP  
Repository  |  UnitOfWork  |  DbContext  |  ADO  
Read/Write  |  Splitting Table  |  Hide tech  |  Update Notes  

Please select a development mode:

Some open source projects that use FreeSql:

🚀 Quick start

dotnet add package FreeSql.Provider.Sqlite

static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
  .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=document.db")
  .UseAutoSyncStructure(true) //automatically synchronize the entity structure to the database
  .Build(); //be sure to define as singleton mode

class Song {
  [Column(IsIdentity = true)]
  public int Id { get; set; }
  public string Title { get; set; }
  public string Url { get; set; }
  public DateTime CreateTime { get; set; }
  
  public ICollection<Tag> Tags { get; set; }
}
class Song_tag {
  public int Song_id { get; set; }
  public Song Song { get; set; }
  
  public int Tag_id { get; set; }
  public Tag Tag { get; set; }
}
class Tag {
  [Column(IsIdentity = true)]
  public int Id { get; set; }
  public string Name { get; set; }
  
  public int? Parent_id { get; set; }
  public Tag Parent { get; set; }
  
  public ICollection<Song> Songs { get; set; }
  public ICollection<Tag> Tags { get; set; }
}

🔎 Query

//OneToOne、ManyToOne
fsql.Select<Tag>().Where(a => a.Parent.Parent.Name == "English").ToList();

//OneToMany
fsql.Select<Tag>().IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo")).ToList();

//ManyToMany
fsql.Select<Song>()
  .IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo"))
  .Where(s => s.Tags.Any(t => t.Name == "Chinese"))
  .ToList();

//Other
fsql.Select<YourType>()
  .Where(a => a.IsDelete == 0)
  .WhereIf(keyword != null, a => a.UserName.Contains(keyword))
  .WhereIf(role_id > 0, a => a.RoleId == role_id)
  .Where(a => a.Nodes.Any(t => t.Parent.Id == t.UserId))
  .Count(out var total)
  .Page(page, size)
  .OrderByDescending(a => a.Id)
  .ToList()

More..

fsql.Select<Song>().Where(a => new[] { 1, 2, 3 }.Contains(a.Id)).ToList();

fsql.Select<Song>().Where(a => a.CreateTime.Date == DateTime.Today).ToList();

fsql.Select<Song>().OrderBy(a => Guid.NewGuid()).Limit(10).ToList();

fsql.Select<Song>().ToList(a => new
{
    a.Id,
    Tags = fsql.Select<Tag>().ToList(),
    SongTags = fsql.Select<SongTag>().Where(b => b.TopicId == a.Id).ToList()
});

More..

🚁 Repository

dotnet add package FreeSql.Repository

[Transactional]
public void Add() {
  var repo = ioc.GetService<BaseRepository<Tag>>();
  repo.DbContextOptions.EnableCascadeSave = true;

  var item = new Tag {
    Name = "testaddsublist",
    Tags = new[] {
      new Tag { Name = "sub1" },
      new Tag { Name = "sub2" }
    }
  };
  repo.Insert(item);
}

Reference: Use TransactionalAttribute and UnitOfWorkManager in ASP.NET Core to Achieve the Multiple Transaction Propagation.

💪 Performance

FreeSql Query & Dapper Query

Elapsed: 00:00:00.6733199; Query Entity Counts: 131072; ORM: Dapper

Elapsed: 00:00:00.4554230; Query Tuple Counts: 131072; ORM: Dapper

Elapsed: 00:00:00.6846146; Query Dynamic Counts: 131072; ORM: Dapper

Elapsed: 00:00:00.6818111; Query Entity Counts: 131072; ORM: FreeSql*

Elapsed: 00:00:00.6060042; Query Tuple Counts: 131072; ORM: FreeSql*

Elapsed: 00:00:00.4211323; Query ToList<Tuple> Counts: 131072; ORM: FreeSql*

Elapsed: 00:00:01.0236285; Query Dynamic Counts: 131072; ORM: FreeSql*

FreeSql ToList & Dapper Query

Elapsed: 00:00:00.6707125; ToList Entity Counts: 131072; ORM: FreeSql*

Elapsed: 00:00:00.6495301; Query Entity Counts: 131072; ORM: Dapper

More..

👯 Contributors

And other friends who made important suggestions for this project, they include:

systemhejiyong, LambertW, mypeng1985, stulzq, movingsam, ALer-R, zouql, 深圳|凉茶, densen2014, LiaoLiaoWuJu, hd2y, tky753, feijie999, constantine, JohnZhou2020, mafeng8, VicBilibily, Soar, quzhen91, homejun, d4ilys etc.

💕 Donation

L*y 58元、花花 88元、麦兜很乖 50元、网络来者 2000元、John 99.99元、alex 666元、bacongao 36元、无名 100元、Eternity 188元、无名 10元、⌒.Helper~..oO 66元、习惯与被习惯 100元、无名 100元、蔡易喋 88.88元、中讯科技 1000元、Good Good Work 24元、炽焰 6.6元、Nothing 100元、兰州天擎赵 500元、哈利路亚 300元、 无名 100元、蛰伏 99.99元、TCYM 66.66元、MOTA 5元、LDZXG 30元、Near 30元、建爽 66元、无名 200元、LambertWu 100元、无名 18.88元、乌龙 50元、无名 100元、陳怼怼 66.66元、陳怼怼 66.66元、丁淮 100元、李伟坚-Excel催化剂 100元、白狐 6.66元、她微笑的脸y 30元、Eternity²º²¹ 588元、夜归柴门 88元、蔡易喋 666.66元、 *礼 10元、litrpa 88元、Alax CHOW 200元、Daily 66元、k*t 66元、蓝 100元、*菜 10元、生命如歌 1000元、山鸡 88元、平凡 100元、大树 1000元、软软的毛毛虫 66.66元、问卷星 2000元、与你无关 5000元

Thank you for your donation

🗄 License

MIT

freesql's People

Contributors

2881099 avatar alexinea avatar ancb520 avatar bobli-net avatar chenlike avatar d4ilys avatar densen2014 avatar dependabot[bot] avatar gbasecontributors avatar hd2y avatar hjkl950217 avatar hyzx86 avatar hzy-6 avatar jianxuanbing avatar jinghongbo avatar kaneleung avatar lambertw avatar luoyunchong avatar ly303550688 avatar pigwing avatar stulzq avatar systemhejiyong avatar taadis avatar tky753 avatar vsuyi avatar wangboshun avatar wch1618 avatar xuejmnet avatar xunapro avatar yinchenjue avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

freesql's Issues

oracle插入,提示ORA-00972: 标识符过长,这个错误

image
实体
[Column(DbType = "varchar2(1500)")] 这个地方用nvarchar(1500)是正常的
public string srvReqstCntt { get; set; }
public string acptTime { get; set; }
public string acptStaffDeptId { get; set; }

json转为实体,json原型如下:
ing parse JS eval
[
{
"acptNumBelgCityName":"泰州",
"concPrsnName":"常**",
"srvReqstTypeName":"家庭业务→网络质量→家庭宽带→自有宽带→功能使用→游戏过程中频繁掉线→全局流转",
"srvReqstCntt":"客户来电表示宽带使用( 所有)出现(频繁掉线不稳定) ,客户所在地址为(安装地址泰州地区靖江靖城街道工农路科技小区科技3区176号2栋2单元502),联系方式(具体联系方式),烦请协调处理。",
"acptTime":"2019-04-15 15:17:05",
"acptStaffDeptId":"0003002101010001000600020023"
},
{
"acptNumBelgCityName":"苏州",
"concPrsnName":"龚**",
"srvReqstTypeName":"移动业务→基础服务→账/详单→全局流转→功能使用→账/详单信息不准确→全局流转",
"srvReqstCntt":"用户参与 2018年苏州任我用关怀活动 送的分钟数500分钟,说自己只使用了116分钟,但是我处查询到本月已经使用了306分钟\r\n,烦请处理",
"acptTime":"2019-04-15 15:12:05",
"acptStaffDeptId":"0003002101010001000600020023"
}
]

关于延迟加载和导航属性反馈

导航属性 是不是 只读取一层的数据。
就是
A 有个属性 B , B 有个属性 C 都是对象。

如果我查询A表的话 B能填充。
但是B里的C 是不是 不填充?
目前看没填充。

然后尝试使用 延迟加载 发现
延迟加载目前是不是只能针对主键 或者 拥有关联表名 Id 和 _Id 为关联的才能使用?
因为有时候 一个表 默认有个自增的id 另外还有一个别的sn当"主键"或者关联字段。
如果关联的字段不是 Id 或 _Id 好像会提示有误。
将来是否能通过某种方式定义掉?

另外反馈一个不像Bug的Bug。时有时无。可能更对象顺序有关。
函数
protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTree()

var tb2 = _tables.Where((a, b) => b > 0 && 
(a.Type == SelectTableInfoType.InnerJoin || a.Type == SelectTableInfoType.LeftJoin || a.Type == SelectTableInfoType.RightJoin) && 
string.IsNullOrEmpty(a.On) == false &&
a.Alias.Contains(prop.Name)).FirstOrDefault(); //判断 b > 0 防止 parent 递归关系

目前使用中发现。
如果 对象中 有多个导航属性 而且 导航属性名称有相互包含的情况。
可能就会出错,提示Int32 太长或太短。不知道是什么原因。

大概就是
class Plan{
TeachingPlanCycle TeachingPlanCycle {get;set;}
TeachingPlan TeachingPlan {get;set;}
......
}
然后 多表查询时 执行的时候。
轮到 TeachingPlan 的时候 因为 _tables Where 顺序的原因 Contains 会匹配到 a__TeachingPlanCycle
导致 返回结果中没有 TeachingPlan 然后就报错了 = =。
PS:
那啥 大佬。。。。
Expression 看得我眼都瞎了。完全不知道怎么调试。。。
想用结果在源码中找了一下午。。。
求告知如何理解。。。。QAQ

目前自己改成

var tb2 = _tables.Where((a, b) => b > 0 &&
(a.Type == SelectTableInfoType.InnerJoin || a.Type == SelectTableInfoType.LeftJoin || a.Type == SelectTableInfoType.RightJoin) &&
string.IsNullOrEmpty(a.On) == false &&
a.Alias.Contains(prop.Name) &&
a.Alias.StartsWith($"{tb.Alias}__") && //开头结尾完全匹配
a.Alias.EndsWith($"__{prop.Name}")   //不清楚会不会有其他情况 求大佬优化
).FirstOrDefault(); //判断 b > 0 防止 parent 递归关系

数据库唯一键 [Column(Unique = “uk_xxxx")]

class AddUniquesInfo {

    public Guid id { get; set; }
    [Column(Unique = "uk_phone")]
    public string phone { get; set; }

    [Column(Unique = "uk_group_index")]
    public string group { get; set; }
    [Column(Unique = "uk_group_index")]
    public int index { get; set; }

    [Column(Unique = "uk_group_index222")]
    public string index22 { get; set; }
}

Unique 指定相同的标识,代表联合唯一键;

启动时间特别慢

第一次启动程序需要20s左右,我想知道这么长的时间都做了什么事情?还是说我的电脑配置不够好?

谢谢

ISelect.GroupBy 查询

Select<Xxxx>()
.GroupBy(a => new { a.CategoryId })
.ToList(a => new {
    a.Key.CategoryId, 
    max = a.Max(a.Value.Score)
});

寻求个解决思路,表格的形式展示数据给客户,进行新增,修改,删除,然后提交到后台

有个问题,寻求个解决思路,前台需要以表格的形式展示数据给客户看,然后客户可以对这些数据进行新增,修改,删除,然后提交到后台,这个时候,后台逻辑需要根据前台的操作,来进行操作数据库,先验证,验证后如果成功则用事务提交,如果失败,则刚刚所有的操作都失败,回滚,验证的时候需要比对修改前和修改后,比对的数据很多,现在用的是datatable,很方便就比对了,我现在打算用泛型,但是没找到具体的思路有没有提供一下的.

实体类实现IEnumerable会报错…

不知道是不是我技艺不精哪里没弄懂……?
实体类T实现IEnumerable接口后,无法执行 CodeFirst.SyncStructure();
错误提示:System.NullReferenceException:“未将对象引用设置到对象的实例。”

IncludeMany 奇葩使用场景讨论

public class User
{
    [Column(IsIdentity = true)]
    public int id { get; set; }

    public int mode { get; set; }
    public string name { get; set; }
    public List<Order> orders { get; set; }
}

public class Order
{
    [Column(IsIdentity = true)]
    public int orderId { get; set; }

    public int userId { get; set; }
    public string name { get; set; }
    public int orderTypeGroup { get; set; }
    public int orderTypeCode { get; set; }
    public OrderTypeGroup OrderTypeGroup { get; set; }
    public OrderType OrderType { get; set; }
}

public class OrderTypeGroup
{
    [Column(IsIdentity = true)]
    public int id { get; set; }

    public int groupCode { get; set; }
    public string groupName { get; set; }
    public List<OrderType> Items { get; set; }
}

public class OrderType
{
    [Column(IsIdentity = true)]
    public int id { get; set; }
    public int groupCode { get; set; }
    public int mode { get; set; }
    public int code { get; set; }
    public string typeName { get; set; }
}

[Fact]
public void Include_OneToManyTTT()
{
    g.sqlite.Delete<User>();
    g.sqlite.Delete<OrderTypeGroup>();
    g.sqlite.Delete<OrderType>();
    g.sqlite.Delete<Order>();
    User[] users = new[]
    {
        new User() {id=1,mode = 1, name = "User1"},
        new User() {id=2,mode = 2, name = "User2"},
    };
    g.sqlite.Insert(users);
    OrderTypeGroup[] orderTypeGroups = new[]
    {
        new OrderTypeGroup() {groupCode = 1, groupName = "Group1"},
        new OrderTypeGroup() {groupCode = 2, groupName = "Group2"},
        new OrderTypeGroup() {groupCode = 3, groupName = "Group3"},
    };
    g.sqlite.Insert(orderTypeGroups);
    var types = new[]
    {
        new OrderType() {code = 1, groupCode = 1, mode = 1, typeName = "type_1_1_1"},
        new OrderType() {code = 2, groupCode = 1, mode = 1, typeName = "type_1_1_2"},
        new OrderType() {code = 3, groupCode = 1, mode = 1, typeName = "type_1_1_3"},
        new OrderType() {code = 1, groupCode = 2, mode = 1, typeName = "type_2_1_1"},
        new OrderType() {code = 2, groupCode = 2, mode = 1, typeName = "type_2_1_2"},
        new OrderType() {code = 3, groupCode = 2, mode = 1, typeName = "type_2_1_3"},
        new OrderType() {code = 1, groupCode = 3, mode = 1, typeName = "type_3_1_1"},
        new OrderType() {code = 2, groupCode = 3, mode = 1, typeName = "type_3_1_2"},
        new OrderType() {code = 3, groupCode = 3, mode = 1, typeName = "type_3_1_3"},
        new OrderType() {code = 1, groupCode = 1, mode = 2, typeName = "type_1_2_1"},
        new OrderType() {code = 2, groupCode = 1, mode = 2, typeName = "type_1_2_2"},
        new OrderType() {code = 3, groupCode = 1, mode = 2, typeName = "type_1_2_3"},
        new OrderType() {code = 1, groupCode = 2, mode = 2, typeName = "type_2_2_1"},
        new OrderType() {code = 2, groupCode = 2, mode = 2, typeName = "type_2_2_2"},
        new OrderType() {code = 3, groupCode = 2, mode = 2, typeName = "type_2_2_3"},
        new OrderType() {code = 1, groupCode = 3, mode = 2, typeName = "type_3_2_1"},
        new OrderType() {code = 2, groupCode = 3, mode = 2, typeName = "type_3_2_2"},
        new OrderType() {code = 3, groupCode = 3, mode = 2, typeName = "type_3_2_3"},
    };
    g.sqlite.Insert(types);

    var orders = new[]
    {
        new Order() {name = "order_1_1", userId = 1, orderTypeGroup = 1, orderTypeCode = 3},
        new Order() {name = "order_1_2", userId = 1, orderTypeGroup = 2, orderTypeCode = 2},
        new Order() {name = "order_1_3", userId = 1, orderTypeGroup = 3, orderTypeCode = 1},
        new Order() {name = "order_2_1", userId = 2, orderTypeGroup = 1, orderTypeCode = 2},
        new Order() {name = "order_2_2", userId = 2, orderTypeGroup = 3, orderTypeCode = 1},
        new Order() {name = "order_2_3", userId = 2, orderTypeGroup = 2, orderTypeCode = 3},
    };
    g.sqlite.Insert(orders);

    var t = g.sqlite.Select<User>()
        .IncludeMany(a => a.orders.Where(o => o.userId == a.id),
            then =>
                then
                    .InnerJoin(o => o.OrderTypeGroup.groupCode == o.orderTypeGroup)
                    .InnerJoin(o => o.OrderType.groupCode == o.orderTypeGroup && o.OrderType.code == o.orderTypeCode && o.OrderType.mode == a.mode)
                    .IncludeMany(o => o.OrderTypeGroup.Items.Where(t => t.groupCode == o.OrderTypeGroup.groupCode && t.mode == a.mode))
        ).ToList();

    var t2 = g.sqlite.Select<OrderTypeGroup>()
                .IncludeMany(o => o.Items.Where(t => t.groupCode == o.groupCode))
            ).ToList();
}

类似的嵌套模式。
当然目前看来这种设计一般是历史遗留问题。

而且应该是不能用延时加载的吧?目前看延时加载是动态编译了 对应 字段的Get。
如果目前这种动态配置的话 可能相同结构对象在不同的使用场景下 数据读取逻辑可能是不一样的。

where Lambda 属性类型为 Guid 时不能执行

提示不支持的表达式,我想知道 为什么不支持guid类型,同字符串一样实现有问题吗?

然后还有一个问题,我使用mysql数据库,打包时打了一堆别的数据库dll,能不能不同数据库独立发包?

OneToOne 一对一,怎么添加数据?

需要安装FreeSql.DbContext

dotnet add package FreeSql
dotnet add package FreeSql.DbContext
dotnet add package FreeSql.Provider.MySqlConnector

无事务的做法

var repoA = orm.GetRepository<A>();
var repoB = orm.GetRepository<B>();

var a = new A();
repoA.Insert(a);
var b = new B { id = a.Id };
repoB.Insert(b);

reposA.Insert(a);,如果 A 有自增,会自动填充 a.id 插入后的值。

后面就可以直接使用 a.id 来添加 b了。

建议能结合EF Core的一些特性来弄

比如能识别下面的映射表及映射主键Id

` ///


/// 映射表
///

protected override void MapTable( EntityTypeBuilder builder ) {
builder.ToTable( "cg_kssqbs" );
}

    /// <summary>
    /// 映射属性
    /// </summary>
    protected override void MapProperties( EntityTypeBuilder<CgKssqbs> builder ) {
        //Id编号
        builder.Property(t => t.Id)
            .HasColumnName("kssqbs_id");
    }`

获取部分列

使用codefirst,repository
获取某个实体列表时,不想过去全部的字段,
能不能指定某个表,然后用一个定义了部分字段的类来获取列表,

谢谢了,最近有点忙,没时间去探索。

讨论新的查询语法

image
@LambertW

[Table(Name = "xxx", SelectFilter = " a.id > 0")]
	class TestInfo {
		[Column(IsIdentity = true, IsPrimary = true)]
		public int Id { get; set; }
		public int TypeGuid { get; set; }
		public TestTypeInfo Type { get; set; }
		public string Title { get; set; }
		public DateTime CreateTime { get; set; }
	}

	class TestTypeInfo {
		[Column(IsIdentity = true)]
		public int Guid { get; set; }
		public int ParentId { get; set; }
		public TestTypeParentInfo Parent { get; set; }
		public string Name { get; set; }
	}

	class TestTypeParentInfo {
		public int Id { get; set; }
		public string Name { get; set; }

		public int ParentId { get; set; }
		public TestTypeParentInfo Parent { get; set; }

		public List<TestTypeInfo> Types { get; set; }
	}

第一个issue我霸占了

祝FreeSql发展壮大

我提几个建议

  1. 提供RoadMap
  2. 在#1的基础上,确定什么待完成
  3. 在#1和#2的基础上,提供完善的(或者说起码基本的)测试案例
  4. #1、#2和#3的基础上,完善每天的build

有了这几个东西,我觉得这个项目成功与否不敢说,但是用起来肯定会安心很多,会明白局限在哪里,适用场景在哪里,然后其他人合作起来也会目标明确。

测试用例合理性讨论

SqlServerInsertTest.cs

增加

[Fact]
public void InsertWithExistData()
{
    var items = GenerateItems(10);

    items[0].Id = (int)insert.AppendData(items[0]).ExecuteIdentity();

    Assert.Equal(0, insert.AppendData(items[0]).ExecuteAffrows());
}

预期item.Id > 0的时候,应该是会跳过吧?
或者是可配置?

[建议]可以优化下where条件的参数传递方式

例:
Ado.Query( "select * from xxx where Id = @id and name=@name", new System.Data.SqlClient.SqlParameter("Id", 1), new System.Data.SqlClient.SqlParameter( "name", "text" ) );
如果能使用:
Ado.Query( "select * from xxx where Id = @0 and name=@1", 1, "text" );
的方式调用的话,就更好了。

多个 IFreeSql 实例,如何注入使用?

第一种方法:定义多个 IFreeSql

1、定义两个标识类:

class MySqlFlag {}
class SqlServerFlag {}

2、在 Startup.cs 中单例注入

public void ConfigureServices(IServiceCollection services)
{
    var fsql1 = new FreeSqlBuilder().UseConnectionString(DataType.MySql, "str1")
        .Build<MySqlFlag>();
    var fsql2 = new FreeSqlBuilder().UseConnectionString(DataType.MySql, "str1")
        .Build<SqlServerFlag>();

    services.AddSingleton<IFreeSql<MySqlFlag>>(fsql1);
    services.AddSingleton<IFreeSql<SqlServerFlag>>(fsql2);
}

3、在 Controller 中使用

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    public ValuesController(IFreeSql<MySqlFlag> mysql, IFreeSql<SqlServerFlag> sqlserver)
    {
    }
}

第二种方法:使用 FreeSql.Clound(推荐)

为 FreeSql 提供跨数据库访问,分布式事务TCC、SAGA解决方案,支持 .NET Core 2.1+, .NET Framework 4.0+.

开源地址:https://github.com/2881099/FreeSql.Cloud

dotnet add package FreeSql.Cloud

or

Install-Package FreeSql.Cloud

public enum DbEnum { db1, db2, db3 }

var fsql = new FreeSqlCloud<DbEnum>(); //提示:泛型可以传入 string
fsql.DistributeTrace = log => Console.WriteLine(log.Split('\n')[0].Trim());

fsql.Register(DbEnum.db1, () => new FreeSqlBuilder()
    .UseConnectionString(DataType.Sqlite, @"Data Source=db1.db")
    .Build());

fsql.Register(DbEnum.db2, () => new FreeSqlBuilder()
    .UseConnectionString(DataType.Sqlite, @"Data Source=db2.db")
    .Build());

fsql.Register(DbEnum.db3, () => new FreeSqlBuilder()
    .UseConnectionString(DataType.Sqlite, @"Data Source=db3.db")
    .Build());

FreeSqlCloud 必须定义成单例模式

new FreeSqlCloud<DbEnum>() 多连接管理

new FreeSqlCloud<DbEnum>("myapp") 开启 TCC/SAGA 事务生效

FreeSqlCloud 的访问方式和 IFreeSql 一样:

fsql.Select<T>();
fsql.Insert<T>();
fsql.Update<T>();
fsql.Delete<T>();

//...

切换数据库:

fsql.Change(DbEnum.db3).Select<T>();
//同一线程,或异步await 后续 fsql.Select/Insert/Update/Delete 操作是 db3

fsql.Use(DbEnum.db3).Select<T>();
//单次有效

自动定向数据库配置:

//对 fsql.CRUD 方法名 + 实体类型 进行拦截,自动定向到对应的数据库,达到自动 Change 切换数据库目的
fsql.EntitySteering = (_, e) =>
{
    switch (e.MethodName)
    {
        case "Select":
            if (e.EntityType == typeof(T))
            {
                //查询 T 自动定向 db3
                e.DBKey = DbEnum.db3;
            }
            else if (e.DBKey == DbEnum.db1)
            {
                //此处像不像读写分离?
                var dbkeyIndex = new Random().Next(0, e.AvailableDBKeys.Length);
                e.DBKey = e.AvailableDBKeys[dbkeyIndex]; //重新定向到其他 db
            }
            break;
        case "Insert":
        case "Update":
        case "Delete":
        case "InsertOrUpdate":
            break;
    }
};

OneToMany 一对多,怎么添加数据?

实体

class Tag {
    [Column(IsIdentity = true)]
    public int Id { get; set; }
    public string Name { get; set; }

    public int? Parent_id { get; set; }
    public virtual Tag Parent { get; set; }

    public virtual ICollection<Tag> Tags { get; set; }
}

IDataFilter.DisableAll/EnableAll合理性探讨

如题,对于实际业务场景,有如下两种filter
SoftDelete,全局默认开放,默认值false;
IsActive,部分场景需要,假设默认值为active。
如果使用 EnableAll ,是否导致SoftDelete也被开启?

关于 FreeSql.DbContext 的请教

DbContext

  • 提供 SaveChanges 方法;
  • 执行队列;

DbSet

  • 提供 Add、AddRange、Remove、RemoveRange、Update、UpdateRange 方法;
  • 以及 Select 属性(连去原有的 FreeSql 查询对象);
  • 私有对象states,存储实体的副本哈希集合,key=实体的主键值,value=实体;

Add/AddRange(entitys)

  • 验证 entitys 主键值,是否存在于 states 中,存在时报错;
  • 验证 entitys 主键中存在自增:
    • 若有,则立即开启 DbContext 事务,按数据库种类执行相应的方法,最终将返回的自增值,赋给entitys的属性;
    • 若无,并且 entitys 无主键值,则报错;
    • 否则,进入【打包执行队列】;
  • 完成时更新 states;

Remove/RemoveRange(entitys)

  • 验证 entitys 主键值,若无则报错;
  • 验证 states 中是否存在,若无则提醒应该先查询,再删除;
  • 删除 states 对应的实体;
  • 清除 entitys 内的自增属性值、Guid 类型的值,那这个 entitys 将变为可 Add 状态;
  • 进入【打包执行队列】;

Update/UpdateRange(entitys)

  • 验证 entitys 主键值,若无则报错;
  • 验证 states 中是否存在,若无则提醒应该先查询,再删除;
  • 进入【打包执行队列】;

Select

  • 立即执行队列中的命令(打包方式),以免脏读到未提交的数据;
  • 查询完成时,更新 states 的值;

更新数据规则

  • 对比 states 中存在的历史快照值,返回即将修改的 fields;

演示

using (var ctx = new SongContext()) {

    ctx.Songs.Select.Where(a => a.Id > 10).ToList();
    //查询结果,进入 states

    var song = new Song { };
    //可插入的 song

    ctx.Songs.Add(song);
    id = song.Id;
    //因有自增类型,立即开启事务执行SQL,返回自增值

    var adds = Enumerable.Range(0, 100)
        .Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
        .ToList();
    //创建一堆无主键值

    ctx.Songs.AddRange(adds);
    //立即执行,将自增值赋给 adds 所有元素,因为有自增类型,如果其他类型,指定传入主键值,不会立即执行

    for (var a = 0; a < adds.Count; a++)
        adds[a].Title = "dkdkdkdk" + a;

    ctx.Songs.UpdateRange(adds);
    //批量修改,进入队列

    ctx.Songs.RemoveRange(adds.Skip(10).Take(20).ToList());
    //批量删除,进入队列,完成时 10-20 元素的主键值会被清除

    //ctx.Songs.Update(adds.First());

    adds.Last().Url = "skldfjlksdjglkjjcccc";
    ctx.Songs.Update(adds.Last());
    //单条修改 urls 的值,进入队列

    //throw new Exception("回滚");

    //ctx.Songs.Select.First();
    //这里做一个查询,会立即打包【执行队列】,避免没有提交的数据,影响查询结果

    ctx.SaveChanges();
    //打包【执行队列】,提交事务
}

两个表查询返回数据,没有配置导航属性

Hello请教个问题,我的客户端表 client 左连接 附件表 attachment,这样写的,

image

我现在需要查询出的字段是 client表的所有字段和 attachment 的 SavePath 字段 这个怎么写,没弄导航属性

在oracle中,db优先时

image
在oracle中,出现当数据类型DbTypeTextFull=DATE(7)出现异常
未实现DATE(7) 类型映射
oracledbfirst.cs 86行.

FreeSql v0.6.1 版本注意了,拆解成了小包引用

FreeSql v0.6.1 版本注意了,拆解成了小包引用;
每个数据库单独包、延时加载也单独了一个包;

  • FreeSql.Extensions.LazyLoading
  • FreeSql.Provider.MySql
  • FreeSql.Provider.PostgreSQL
  • FreeSql.Provider.SqlServer
  • FreeSql.Provider.Sqlite
  • FreeSql.Provider.Oracle
  • 移除了 IFreeSql.Cache,以及 ISelect.Caching 方法;
  • 移除了 IFreeSql.Log,包括内部原有的日志输出,改为 Trace.WriteLine;
  • IAdo.Query 读取返回变为 List<Dictionary<string, object>>;
  • 定义 IFreeSql 和以前一样,移除了 UseCache、UseLogger 方法;

https://github.com/2881099/FreeSql
如使用出现问题,提交 issues 在 10分钟内为您解答

Aop.ConfigEntity 新功能

自定义特性

以下的示例代码,FreeSql 使用 EFCore 的实体特性。

fsql.CodeFirst.ConfigEntity<ModelAopConfigEntity>(a => a.Property(b => b.pkid).IsPrimary(true));

fsql.Aop.ConfigEntity = (s, e) => {
  var attr = e.EntityType.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.Schema.TableAttribute), false).FirstOrDefault() as System.ComponentModel.DataAnnotations.Schema.TableAttribute;
  if (attr != null)
    e.ModifyResult.Name = attr.Name;
};
fsql.Aop.ConfigEntityProperty = (s, e) => {
  if (e.Property.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false).Any())
    e.ModifyResult.IsPrimary = true;
};

[System.ComponentModel.DataAnnotations.Schema.Table("xxx")]
class ModelAopConfigEntity {
  [System.ComponentModel.DataAnnotations.Key]
  [Column(IsPrimary = false)]
  public int pkid { get; set; }
}

oracle升级0.1.1后的新问题

List t1 = context.fsql.Select().Where(a => a.Id > 0).ToList();
执行这个的时候,报Oracle.ManagedDataAccess.Client.OracleException:“ORA-00955: 名称已由现有对象使用
ORA-06512: 在 line 4”
应该是UseAutoSyncStructure验证有错

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.