mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
Merge branch 'master' of https://github.com/dotnetcore/FreeSql
This commit is contained in:
commit
13b85d9c32
@ -1,17 +1,24 @@
|
|||||||
using FreeSql;
|
#if NET40
|
||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#else
|
||||||
using FreeSql.DataAnnotations;
|
using FreeSql.DataAnnotations;
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
namespace FreeSql
|
namespace FreeSql
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Entity base class, including CreateTime/UpdateTime/IsDeleted, the CRUD methods, and ID primary key definition.
|
||||||
|
/// <para></para>
|
||||||
/// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 方法、以及 ID 主键定义 的实体基类
|
/// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 方法、以及 ID 主键定义 的实体基类
|
||||||
/// <para></para>
|
/// <para></para>
|
||||||
|
/// When TKey is int/long, the Id is set to be an auto-incremented primary key
|
||||||
|
/// <para></para>
|
||||||
/// 当 TKey 为 int/long 时,Id 主键被设为自增值主键
|
/// 当 TKey 为 int/long 时,Id 主键被设为自增值主键
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
@ -21,25 +28,26 @@ namespace FreeSql
|
|||||||
{
|
{
|
||||||
static BaseEntity()
|
static BaseEntity()
|
||||||
{
|
{
|
||||||
var tkeyType = typeof(TKey)?.NullableTypeOrThis();
|
var keyType = typeof(TKey).NullableTypeOrThis();
|
||||||
if (tkeyType == typeof(int) || tkeyType == typeof(long))
|
if (keyType == typeof(int) || keyType == typeof(long))
|
||||||
BaseEntity.ConfigEntity(typeof(TEntity), t => t.Property("Id").IsIdentity(true));
|
ConfigEntity(typeof(TEntity), t => t.Property("Id").IsIdentity(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Primary key <br />
|
||||||
/// 主键
|
/// 主键
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = 1)]
|
[Column(Position = 1)]
|
||||||
public virtual TKey Id { get; set; }
|
public virtual TKey Id { get; set; }
|
||||||
|
|
||||||
#if net40
|
#if !NET40
|
||||||
#else
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Get data based on the value of the primary key <br />
|
||||||
/// 根据主键值获取数据
|
/// 根据主键值获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
async public static Task<TEntity> FindAsync(TKey id)
|
public static async Task<TEntity> FindAsync(TKey id)
|
||||||
{
|
{
|
||||||
var item = await Select.WhereDynamic(id).FirstAsync();
|
var item = await Select.WhereDynamic(id).FirstAsync();
|
||||||
(item as BaseEntity<TEntity>)?.Attach();
|
(item as BaseEntity<TEntity>)?.Attach();
|
||||||
@ -48,6 +56,7 @@ namespace FreeSql
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Get data based on the value of the primary key <br />
|
||||||
/// 根据主键值获取数据
|
/// 根据主键值获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
@ -61,6 +70,8 @@ namespace FreeSql
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Entity base class, including CreateTime/UpdateTime/IsDeleted, and sync/async CRUD methods.
|
||||||
|
/// <para></para>
|
||||||
/// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步和同步方法的实体基类
|
/// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步和同步方法的实体基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
@ -69,88 +80,97 @@ namespace FreeSql
|
|||||||
{
|
{
|
||||||
bool UpdateIsDeleted(bool value)
|
bool UpdateIsDeleted(bool value)
|
||||||
{
|
{
|
||||||
if (this.Repository == null)
|
if (Repository is null)
|
||||||
|
{
|
||||||
return Orm.Update<TEntity>(this as TEntity)
|
return Orm.Update<TEntity>(this as TEntity)
|
||||||
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
||||||
.Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrows() == 1;
|
.Set(a => (a as BaseEntity).IsDeleted, IsDeleted = value).ExecuteAffrows() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.IsDeleted = value;
|
IsDeleted = value;
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
return this.Repository.Update(this as TEntity) == 1;
|
return Repository.Update(this as TEntity) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To delete data <br />
|
||||||
/// 删除数据
|
/// 删除数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="physicalDelete">是否物理删除</param>
|
/// <param name="physicalDelete">To flag whether to delete the physical level of the data</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual bool Delete(bool physicalDelete = false)
|
public virtual bool Delete(bool physicalDelete = false)
|
||||||
{
|
{
|
||||||
if (physicalDelete == false) return this.UpdateIsDeleted(true);
|
if (physicalDelete == false)
|
||||||
if (this.Repository == null)
|
return UpdateIsDeleted(true);
|
||||||
|
|
||||||
|
if (Repository is null)
|
||||||
return Orm.Delete<TEntity>(this as TEntity).ExecuteAffrows() == 1;
|
return Orm.Delete<TEntity>(this as TEntity).ExecuteAffrows() == 1;
|
||||||
|
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
return this.Repository.Delete(this as TEntity) == 1;
|
return Repository.Delete(this as TEntity) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To recover deleted data <br />
|
||||||
/// 恢复删除的数据
|
/// 恢复删除的数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual bool Restore() => this.UpdateIsDeleted(false);
|
public virtual bool Restore() => UpdateIsDeleted(false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To update data <br />
|
||||||
/// 更新数据
|
/// 更新数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual bool Update()
|
public virtual bool Update()
|
||||||
{
|
{
|
||||||
this.UpdateTime = DateTime.Now;
|
UpdateTime = DateTime.Now;
|
||||||
if (this.Repository == null)
|
if (Repository is null)
|
||||||
|
{
|
||||||
return Orm.Update<TEntity>()
|
return Orm.Update<TEntity>()
|
||||||
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
||||||
.SetSource(this as TEntity).ExecuteAffrows() == 1;
|
.SetSource(this as TEntity).ExecuteAffrows() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
return this.Repository.Update(this as TEntity) == 1;
|
return Repository.Update(this as TEntity) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To insert data <br />
|
||||||
/// 插入数据
|
/// 插入数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual TEntity Insert()
|
public virtual TEntity Insert()
|
||||||
{
|
{
|
||||||
this.CreateTime = DateTime.Now;
|
CreateTime = DateTime.Now;
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
|
return Repository.Insert(this as TEntity);
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
|
||||||
return this.Repository.Insert(this as TEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To insert or update data <br />
|
||||||
/// 更新或插入
|
/// 更新或插入
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual TEntity Save()
|
public virtual TEntity Save()
|
||||||
{
|
{
|
||||||
this.UpdateTime = DateTime.Now;
|
UpdateTime = DateTime.Now;
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
|
return Repository.InsertOrUpdate(this as TEntity);
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
|
||||||
return this.Repository.InsertOrUpdate(this as TEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To completely save the navigation properties of the entity in the form of sub-tables. <br />
|
||||||
/// 【完整】保存导航属性,子表
|
/// 【完整】保存导航属性,子表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="navigatePropertyName">导航属性名</param>
|
/// <param name="navigatePropertyName">Navigation property name</param>
|
||||||
public virtual void SaveMany(string navigatePropertyName)
|
public virtual void SaveMany(string navigatePropertyName)
|
||||||
{
|
{
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
|
Repository.SaveMany(this as TEntity, navigatePropertyName);
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
|
||||||
this.Repository.SaveMany(this as TEntity, navigatePropertyName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,23 @@
|
|||||||
|
#if NET40
|
||||||
using FreeSql;
|
using FreeSql.DataAnnotations;
|
||||||
|
|
||||||
|
#else
|
||||||
using FreeSql.DataAnnotations;
|
using FreeSql.DataAnnotations;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
namespace FreeSql
|
namespace FreeSql
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Entity base class, including CreateTime/UpdateTime/IsDeleted, the async CRUD methods, and ID primary key definition.
|
||||||
|
/// <para></para>
|
||||||
/// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 异步方法、以及 ID 主键定义 的实体基类
|
/// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 异步方法、以及 ID 主键定义 的实体基类
|
||||||
/// <para></para>
|
/// <para></para>
|
||||||
|
/// When TKey is int/long, the Id is set to be an auto-incremented primary key
|
||||||
|
/// <para></para>
|
||||||
/// 当 TKey 为 int/long 时,Id 主键被设为自增值主键
|
/// 当 TKey 为 int/long 时,Id 主键被设为自增值主键
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
@ -18,128 +27,138 @@ namespace FreeSql
|
|||||||
{
|
{
|
||||||
static BaseEntityAsync()
|
static BaseEntityAsync()
|
||||||
{
|
{
|
||||||
var tkeyType = typeof(TKey)?.NullableTypeOrThis();
|
var keyType = typeof(TKey).NullableTypeOrThis();
|
||||||
if (tkeyType == typeof(int) || tkeyType == typeof(long))
|
if (keyType == typeof(int) || keyType == typeof(long))
|
||||||
BaseEntity.ConfigEntity(typeof(TEntity), t => t.Property("Id").IsIdentity(true));
|
ConfigEntity(typeof(TEntity), t => t.Property("Id").IsIdentity(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Primary key <br />
|
||||||
/// 主键
|
/// 主键
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = 1)]
|
[Column(Position = 1)]
|
||||||
public virtual TKey Id { get; set; }
|
public virtual TKey Id { get; set; }
|
||||||
|
|
||||||
#if net40
|
#if !NET40
|
||||||
#else
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Get data based on the value of the primary key <br />
|
||||||
/// 根据主键值获取数据
|
/// 根据主键值获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
async public static Task<TEntity> FindAsync(TKey id)
|
public static async Task<TEntity> FindAsync(TKey id)
|
||||||
{
|
{
|
||||||
var item = await Select.WhereDynamic(id).FirstAsync();
|
var item = await Select.WhereDynamic(id).FirstAsync();
|
||||||
(item as BaseEntity<TEntity>)?.Attach();
|
(item as BaseEntity<TEntity>)?.Attach();
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Entity base class, including CreateTime/UpdateTime/IsDeleted, and async CRUD methods.
|
||||||
|
/// <para></para>
|
||||||
/// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步方法的实体基类
|
/// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步方法的实体基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
[Table(DisableSyncStructure = true)]
|
[Table(DisableSyncStructure = true)]
|
||||||
public abstract class BaseEntityAsync<TEntity> : BaseEntityReadOnly<TEntity> where TEntity : class
|
public abstract class BaseEntityAsync<TEntity> : BaseEntityReadOnly<TEntity> where TEntity : class
|
||||||
{
|
{
|
||||||
#if net40
|
#if !NET40
|
||||||
#else
|
|
||||||
async Task<bool> UpdateIsDeletedAsync(bool value)
|
async Task<bool> UpdateIsDeletedAsync(bool value)
|
||||||
{
|
{
|
||||||
if (this.Repository == null)
|
if (Repository is null)
|
||||||
|
{
|
||||||
return await Orm.Update<TEntity>(this as TEntity)
|
return await Orm.Update<TEntity>(this as TEntity)
|
||||||
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
||||||
.Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrowsAsync() == 1;
|
.Set(a => (a as BaseEntity).IsDeleted, IsDeleted = value).ExecuteAffrowsAsync() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.IsDeleted = value;
|
IsDeleted = value;
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
return await this.Repository.UpdateAsync(this as TEntity) == 1;
|
return await Repository.UpdateAsync(this as TEntity) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To delete data <br />
|
||||||
/// 删除数据
|
/// 删除数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="physicalDelete">是否物理删除</param>
|
/// <param name="physicalDelete">To flag whether to delete the physical level of the data</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
async public virtual Task<bool> DeleteAsync(bool physicalDelete = false)
|
public virtual async Task<bool> DeleteAsync(bool physicalDelete = false)
|
||||||
{
|
{
|
||||||
if (physicalDelete == false) return await this.UpdateIsDeletedAsync(true);
|
if (physicalDelete == false)
|
||||||
if (this.Repository == null)
|
return await UpdateIsDeletedAsync(true);
|
||||||
|
|
||||||
|
if (Repository is null)
|
||||||
return await Orm.Delete<TEntity>(this as TEntity).ExecuteAffrowsAsync() == 1;
|
return await Orm.Delete<TEntity>(this as TEntity).ExecuteAffrowsAsync() == 1;
|
||||||
|
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
return await this.Repository.DeleteAsync(this as TEntity) == 1;
|
return await Repository.DeleteAsync(this as TEntity) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To recover deleted data <br />
|
||||||
/// 恢复删除的数据
|
/// 恢复删除的数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual Task<bool> RestoreAsync() => this.UpdateIsDeletedAsync(false);
|
public virtual Task<bool> RestoreAsync() => UpdateIsDeletedAsync(false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To update data <br />
|
||||||
/// 更新数据
|
/// 更新数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
async public virtual Task<bool> UpdateAsync()
|
public virtual async Task<bool> UpdateAsync()
|
||||||
{
|
{
|
||||||
this.UpdateTime = DateTime.Now;
|
UpdateTime = DateTime.Now;
|
||||||
if (this.Repository == null)
|
if (Repository is null)
|
||||||
|
{
|
||||||
return await Orm.Update<TEntity>()
|
return await Orm.Update<TEntity>()
|
||||||
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction())
|
||||||
.SetSource(this as TEntity).ExecuteAffrowsAsync() == 1;
|
.SetSource(this as TEntity).ExecuteAffrowsAsync() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
return await this.Repository.UpdateAsync(this as TEntity) == 1;
|
return await Repository.UpdateAsync(this as TEntity) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To insert data <br />
|
||||||
/// 插入数据
|
/// 插入数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual Task<TEntity> InsertAsync()
|
public virtual Task<TEntity> InsertAsync()
|
||||||
{
|
{
|
||||||
this.CreateTime = DateTime.Now;
|
CreateTime = DateTime.Now;
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
|
return Repository.InsertAsync(this as TEntity);
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
|
||||||
return this.Repository.InsertAsync(this as TEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To insert or update data <br />
|
||||||
/// 更新或插入
|
/// 更新或插入
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual Task<TEntity> SaveAsync()
|
public virtual Task<TEntity> SaveAsync()
|
||||||
{
|
{
|
||||||
this.UpdateTime = DateTime.Now;
|
UpdateTime = DateTime.Now;
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
|
return Repository.InsertOrUpdateAsync(this as TEntity);
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
|
||||||
return this.Repository.InsertOrUpdateAsync(this as TEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To completely save the navigation properties of the entity in the form of sub-tables. <br />
|
||||||
/// 【完整】保存导航属性,子表
|
/// 【完整】保存导航属性,子表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="navigatePropertyName">导航属性名</param>
|
/// <param name="navigatePropertyName">Navigation property name</param>
|
||||||
public virtual Task SaveManyAsync(string navigatePropertyName)
|
public virtual Task SaveManyAsync(string navigatePropertyName)
|
||||||
{
|
{
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||||
|
return Repository.SaveManyAsync(this as TEntity, navigatePropertyName);
|
||||||
this.Repository.UnitOfWork = _resolveUow?.Invoke();
|
|
||||||
return this.Repository.SaveManyAsync(this as TEntity, navigatePropertyName);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,44 +1,53 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
using FreeSql.DataAnnotations;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
// ReSharper disable InconsistentlySynchronizedField
|
||||||
namespace FreeSql
|
namespace FreeSql
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Entity base class, including CreateTime/UpdateTime/IsDeleted.
|
||||||
|
/// <para></para>
|
||||||
/// 包括 CreateTime/UpdateTime/IsDeleted 的实体基类
|
/// 包括 CreateTime/UpdateTime/IsDeleted 的实体基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Table(DisableSyncStructure = true)]
|
[Table(DisableSyncStructure = true)]
|
||||||
public abstract class BaseEntity
|
public abstract class BaseEntity
|
||||||
{
|
{
|
||||||
internal static IFreeSql _ormPriv;
|
internal static IFreeSql _ormPriv;
|
||||||
|
|
||||||
|
private const string ErrorMessageTemplate = @"使用前请初始化:
|
||||||
|
BaseEntity.Initialization(new FreeSqlBuilder()
|
||||||
|
.UseAutoSyncStructure(true)
|
||||||
|
.UseConnectionString(DataType.Sqlite, ""data source=test.db;max pool size=5"")
|
||||||
|
.Build());";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局 IFreeSql orm 对象
|
/// Global IFreeSql ORM Object <br />
|
||||||
|
/// 全局 IFreeSql ORM 对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IFreeSql Orm => _ormPriv ?? throw new Exception(@"使用前请初始化 BaseEntity.Initialization(new FreeSqlBuilder()
|
public static IFreeSql Orm => _ormPriv ?? throw new Exception(ErrorMessageTemplate);
|
||||||
.UseAutoSyncStructure(true)
|
|
||||||
.UseConnectionString(DataType.Sqlite, ""data source=test.db;max pool size=5"")
|
|
||||||
.Build());");
|
|
||||||
internal static Func<IUnitOfWork> _resolveUow;
|
internal static Func<IUnitOfWork> _resolveUow;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化BaseEntity
|
/// To initialize the BaseEntity <br />
|
||||||
/// BaseEntity.Initialization(new FreeSqlBuilder()
|
/// 初始化 BaseEntity
|
||||||
/// <para></para>
|
/// <para></para>
|
||||||
/// .UseAutoSyncStructure(true)
|
/// BaseEntity.Initialization( <br />
|
||||||
/// <para></para>
|
/// new FreeSqlBuilder() <br />
|
||||||
/// .UseConnectionString(DataType.Sqlite, "data source=test.db;max pool size=5")
|
/// .UseAutoSyncStructure(true) <br />
|
||||||
/// <para></para>
|
/// .UseConnectionString(DataType.Sqlite, "data source=test.db;max pool size=5") <br />
|
||||||
/// .Build());
|
/// .Build());
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fsql">IFreeSql orm 对象</param>
|
/// <param name="fsql">IFreeSql ORM Object</param>
|
||||||
/// <param name="resolveUow">工作单元(事务)委托,如果不使用事务请传 null<para></para>解释:由于AsyncLocal平台兼容不好,所以交给外部管理</param>
|
/// <param name="resolveUow">工作单元(事务)委托,如果不使用事务请传 null<para></para>解释:由于AsyncLocal平台兼容不好,所以交给外部管理</param>
|
||||||
public static void Initialization(IFreeSql fsql, Func<IUnitOfWork> resolveUow)
|
public static void Initialization(IFreeSql fsql, Func<IUnitOfWork> resolveUow)
|
||||||
{
|
{
|
||||||
@ -52,21 +61,24 @@ namespace FreeSql
|
|||||||
_ormPriv.CodeFirst.ConfigEntity(cei.EntityType, cei.Fluent);
|
_ormPriv.CodeFirst.ConfigEntity(cei.EntityType, cei.Fluent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_resolveUow = resolveUow;
|
_resolveUow = resolveUow;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfigEntityInfo
|
class ConfigEntityInfo
|
||||||
{
|
{
|
||||||
public Type EntityType;
|
public Type EntityType;
|
||||||
public Action<TableFluent> Fluent;
|
public Action<TableFluent> Fluent;
|
||||||
}
|
}
|
||||||
static ConcurrentQueue<ConfigEntityInfo> _configEntityQueues = new ConcurrentQueue<ConfigEntityInfo>();
|
|
||||||
static object _configEntityLock = new object();
|
static readonly ConcurrentQueue<ConfigEntityInfo> _configEntityQueues = new();
|
||||||
|
static readonly object _configEntityLock = new();
|
||||||
|
|
||||||
internal static void ConfigEntity(Type entityType, Action<TableFluent> fluent)
|
internal static void ConfigEntity(Type entityType, Action<TableFluent> fluent)
|
||||||
{
|
{
|
||||||
lock (_configEntityLock)
|
lock (_configEntityLock)
|
||||||
{
|
{
|
||||||
if (_ormPriv == null)
|
if (_ormPriv is null)
|
||||||
_configEntityQueues.Enqueue(new ConfigEntityInfo { EntityType = entityType, Fluent = fluent });
|
_configEntityQueues.Enqueue(new ConfigEntityInfo { EntityType = entityType, Fluent = fluent });
|
||||||
else
|
else
|
||||||
_ormPriv.CodeFirst.ConfigEntity(entityType, fluent);
|
_ormPriv.CodeFirst.ConfigEntity(entityType, fluent);
|
||||||
@ -74,31 +86,45 @@ namespace FreeSql
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Created time <br />
|
||||||
/// 创建时间
|
/// 创建时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = -4)]
|
[Column(Position = -4)]
|
||||||
public virtual DateTime CreateTime { get; set; } = DateTime.Now;
|
public virtual DateTime CreateTime { get; set; } = DateTime.Now;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Updated time <br />
|
||||||
/// 更新时间
|
/// 更新时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = -3)]
|
[Column(Position = -3)]
|
||||||
public virtual DateTime UpdateTime { get; set; }
|
public virtual DateTime UpdateTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Logical Delete <br />
|
||||||
/// 逻辑删除
|
/// 逻辑删除
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = -2)]
|
[Column(Position = -2)]
|
||||||
public virtual bool IsDeleted { get; set; }
|
public virtual bool IsDeleted { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Sort <br />
|
||||||
/// 排序
|
/// 排序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(Position = -1)]
|
[Column(Position = -1)]
|
||||||
public virtual int Sort { get; set; }
|
public virtual int Sort { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A readonly entity base class, including CreateTime/UpdateTime/IsDeleted.
|
||||||
|
/// <para></para>
|
||||||
|
/// 包括 CreateTime/UpdateTime/IsDeleted 的只读实体基类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
[Table(DisableSyncStructure = true)]
|
[Table(DisableSyncStructure = true)]
|
||||||
public abstract class BaseEntityReadOnly<TEntity> : BaseEntity where TEntity : class
|
public abstract class BaseEntityReadOnly<TEntity> : BaseEntity where TEntity : class
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// To query data <br />
|
||||||
/// 查询数据
|
/// 查询数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@ -107,68 +133,92 @@ namespace FreeSql
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
var select = Orm.Select<TEntity>()
|
var select = Orm.Select<TEntity>()
|
||||||
.TrackToList(TrackToList) //自动为每个元素 Attach
|
.TrackToList(TrackToList) //自动为每个元素 Attach
|
||||||
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction(false));
|
.WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction(false));
|
||||||
return select.WhereCascade(a => (a as BaseEntity).IsDeleted == false);
|
return select.WhereCascade(a => (a as BaseEntity).IsDeleted == false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TrackToList(object list)
|
static void TrackToList(object list)
|
||||||
{
|
{
|
||||||
if (list == null) return;
|
if (list is null)
|
||||||
var ls = list as IList<TEntity>;
|
return;
|
||||||
if (ls == null)
|
|
||||||
|
if (list is not IList<TEntity> ls)
|
||||||
{
|
{
|
||||||
var ie = list as IEnumerable;
|
if (list is not IEnumerable ie)
|
||||||
if (ie == null) return;
|
return;
|
||||||
|
|
||||||
var isFirst = true;
|
var isFirst = true;
|
||||||
IBaseRepository<TEntity> berepo = null;
|
IBaseRepository<TEntity> baseRepo = null;
|
||||||
|
|
||||||
foreach (var item in ie)
|
foreach (var item in ie)
|
||||||
{
|
{
|
||||||
if (item == null) return;
|
if (item is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isFirst)
|
if (isFirst)
|
||||||
{
|
{
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
var itemType = item.GetType();
|
var itemType = item.GetType();
|
||||||
if (itemType == typeof(object)) return;
|
if (itemType == typeof(object)) return;
|
||||||
if (itemType.FullName.Contains("FreeSqlLazyEntity__")) itemType = itemType.BaseType;
|
if (itemType.FullName!.Contains("FreeSqlLazyEntity__")) itemType = itemType.BaseType;
|
||||||
if (Orm.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return;
|
if (Orm.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return;
|
||||||
if (item is BaseEntity<TEntity> == false) return;
|
if (item is not BaseEntity<TEntity>) return;
|
||||||
}
|
}
|
||||||
var beitem = item as BaseEntity<TEntity>;
|
|
||||||
if (beitem != null)
|
if (item is BaseEntity<TEntity> entity)
|
||||||
{
|
{
|
||||||
if (berepo == null) berepo = Orm.GetRepository<TEntity>();
|
baseRepo ??= Orm.GetRepository<TEntity>();
|
||||||
beitem.Repository = berepo;
|
entity.Repository = baseRepo;
|
||||||
beitem.Attach();
|
entity.Attach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ls.Any() == false) return;
|
|
||||||
if (ls.FirstOrDefault() is BaseEntity<TEntity> == false) return;
|
if (ls.Any() == false)
|
||||||
if (Orm.CodeFirst.GetTableByEntity(typeof(TEntity))?.Primarys.Any() != true) return;
|
return;
|
||||||
|
|
||||||
|
if (ls.FirstOrDefault() is not BaseEntity<TEntity>)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Orm.CodeFirst.GetTableByEntity(typeof(TEntity))?.Primarys.Any() != true)
|
||||||
|
return;
|
||||||
|
|
||||||
IBaseRepository<TEntity> repo = null;
|
IBaseRepository<TEntity> repo = null;
|
||||||
|
|
||||||
foreach (var item in ls)
|
foreach (var item in ls)
|
||||||
{
|
{
|
||||||
var beitem = item as BaseEntity<TEntity>;
|
if (item is BaseEntity<TEntity> entity)
|
||||||
if (beitem != null)
|
|
||||||
{
|
{
|
||||||
if (repo == null) repo = Orm.GetRepository<TEntity>();
|
repo ??= Orm.GetRepository<TEntity>();
|
||||||
beitem.Repository = repo;
|
entity.Repository = repo;
|
||||||
beitem.Attach();
|
entity.Attach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
|
/// Query conditions <br />
|
||||||
|
/// 查询条件,Where(a => a.Id> 10)
|
||||||
|
/// <para></para>
|
||||||
|
/// Support navigation object query <br />
|
||||||
|
/// 支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exp">lambda表达式</param>
|
/// <param name="exp">lambda表达式</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => Select.Where(exp);
|
public static ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => Select.Where(exp);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询条件,Where(true, a => a.Id > 10),支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com")
|
/// Query conditions <br />
|
||||||
|
/// 查询条件,Where(true, a => a.Id > 10)
|
||||||
|
/// <para></para>
|
||||||
|
/// Support navigation object query <br />
|
||||||
|
/// 支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com")
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="condition">true 时生效</param>
|
/// <param name="condition">true 时生效</param>
|
||||||
/// <param name="exp">lambda表达式</param>
|
/// <param name="exp">lambda表达式</param>
|
||||||
@ -176,21 +226,21 @@ namespace FreeSql
|
|||||||
public static ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => Select.WhereIf(condition, exp);
|
public static ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => Select.WhereIf(condition, exp);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Repository object. <br />
|
||||||
/// 仓储对象
|
/// 仓储对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected IBaseRepository<TEntity> Repository { get; set; }
|
protected IBaseRepository<TEntity> Repository { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 附加实体,在更新数据时,只更新变化的部分
|
/// To Attach entities. When updating data, only the changed part is updated. <br />
|
||||||
|
/// 附加实体。在更新数据时,只更新变化的部分
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TEntity Attach()
|
public TEntity Attach()
|
||||||
{
|
{
|
||||||
if (this.Repository == null)
|
Repository ??= Orm.GetRepository<TEntity>();
|
||||||
this.Repository = Orm.GetRepository<TEntity>();
|
|
||||||
|
|
||||||
var item = this as TEntity;
|
var item = this as TEntity;
|
||||||
this.Repository.Attach(item);
|
Repository.Attach(item);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,8 +6,8 @@
|
|||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Authors>FreeSql;ncc;YeXiangQin</Authors>
|
<Authors>FreeSql;ncc;YeXiangQin</Authors>
|
||||||
<Description>BaseEntity 是一种极简单的 CodeFirst 开发方式,特别对单表或多表CRUD,利用继承节省了每个实体类的重复属性(创建时间、ID等字段),软件删除等功能,进行 crud 操作时不必时常考虑仓储的使用.</Description>
|
<Description>BaseEntity 是一种极简单的 CodeFirst 开发方式,特别对单表或多表CRUD,利用继承节省了每个实体类的重复属性(创建时间、ID等字段),软件删除等功能,进行 crud 操作时不必时常考虑仓储的使用.</Description>
|
||||||
<PackageProjectUrl>https://github.com/2881099/FreeSql/tree/master/Extensions/FreeSql.Extensions.BaseEntity</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/dotnetcore/FreeSql/tree/master/Extensions/FreeSql.Extensions.BaseEntity</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/2881099/FreeSql/tree/master/Extensions/FreeSql.Extensions.BaseEntity</RepositoryUrl>
|
<RepositoryUrl>https://github.com/dotnetcore/FreeSql/tree/master/Extensions/FreeSql.Extensions.BaseEntity</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageTags>FreeSql;ORM;BaseEntity</PackageTags>
|
<PackageTags>FreeSql;ORM;BaseEntity</PackageTags>
|
||||||
@ -19,6 +19,7 @@
|
|||||||
<SignAssembly>true</SignAssembly>
|
<SignAssembly>true</SignAssembly>
|
||||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||||
<DelaySign>false</DelaySign>
|
<DelaySign>false</DelaySign>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
129
Extensions/FreeSql.Extensions.BaseEntity/README.MD
Normal file
129
Extensions/FreeSql.Extensions.BaseEntity/README.MD
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
[中文](README.zh-CN.md) | **English**
|
||||||
|
|
||||||
|
# Preface
|
||||||
|
|
||||||
|
I have tried ADO.NET, Dapper, EF, and Repository storage, and even wrote a generator tool myself to do common CRUD operations.
|
||||||
|
|
||||||
|
Their operation is inconvenient:
|
||||||
|
|
||||||
|
- Need to declare before use;
|
||||||
|
|
||||||
|
- Each entity class corresponds to an operation class (or DAL, DbContext, Repository).
|
||||||
|
|
||||||
|
BaseEntity is a very simple way of CodeFirst development, especially for single-table or multi-table CRUD operations. BaseEntity uses "inheritance" to save the repetitive code (creation time, ID and other fields) and functions of each entity class, and at the same time, it is not necessary to consider the use of repository when performing CURD operations.
|
||||||
|
|
||||||
|
|
||||||
|
This article will introduce a very simple CRUD operation method of BaseEntity.
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
- Automatically migrate the entity structure (CodeFirst) to the database;
|
||||||
|
|
||||||
|
- Directly perform CRUD operations on entities;
|
||||||
|
|
||||||
|
- Simplify user-defined entity types, eliminating hard-coded primary keys, common fields and their configuration (such as CreateTime, UpdateTime);
|
||||||
|
|
||||||
|
- Logic delete of single-table and multi-table query;
|
||||||
|
|
||||||
|
# Declaring
|
||||||
|
|
||||||
|
> dotnet add package FreeSql.Extensions.BaseEntity
|
||||||
|
|
||||||
|
> dotnet add package FreeSql.Provider.Sqlite
|
||||||
|
|
||||||
|
1. Define an auto-increment primary key of type `int`. When the `TKey` of `BaseEntity` is specified as `int/long`, the primary key will be considered as auto-increment;
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class UserGroup : BaseEntity<UserGroup, int>
|
||||||
|
{
|
||||||
|
public string GroupName { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't want the primary key to be an auto-increment key, you can override the attribute:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class UserGroup : BaseEntity<UserGroup, int>
|
||||||
|
{
|
||||||
|
[Column(IsIdentity = false)]
|
||||||
|
public override int Id { get; set; }
|
||||||
|
public string GroupName { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> For more information about the attributes of entities, please refer to: https://github.com/dotnetcore/FreeSql/wiki/Entity-Attributes
|
||||||
|
|
||||||
|
2. Define an entity whose primary key is Guid type, when saving data, it will automatically generate ordered and non-repeated Guid values (you don't need to specify `Guid.NewGuid()` yourself);
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class User : BaseEntity<UserGroup, Guid>
|
||||||
|
{
|
||||||
|
public string UserName { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage of CRUD
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
//Insert Data
|
||||||
|
var item = new UserGroup { GroupName = "Group One" };
|
||||||
|
item.Insert();
|
||||||
|
|
||||||
|
//Update Data
|
||||||
|
item.GroupName = "Group Two";
|
||||||
|
item.Update();
|
||||||
|
|
||||||
|
//Insert or Update Data
|
||||||
|
item.Save();
|
||||||
|
|
||||||
|
//Logic Delete
|
||||||
|
item.Delete();
|
||||||
|
|
||||||
|
//Recover Logic Delete
|
||||||
|
item.Restore();
|
||||||
|
|
||||||
|
//Get the object by the primary key
|
||||||
|
var item = UserGroup.Find(1);
|
||||||
|
|
||||||
|
//Query Data
|
||||||
|
var items = UserGroup.Where(a => a.Id > 10).ToList();
|
||||||
|
```
|
||||||
|
|
||||||
|
`{ENTITY_TYPE}.Select` returns a query object, the same as `FreeSql.ISelect`.
|
||||||
|
|
||||||
|
In the multi-table query, the logic delete condition will be attached to the query of each table.
|
||||||
|
|
||||||
|
> For more information about query data, please refer to: https://github.com/2881099/FreeSql/wiki/Query-Data
|
||||||
|
|
||||||
|
# Transaction Suggestion
|
||||||
|
|
||||||
|
Because the `AsyncLocal` platform is not compatible, the transaction is managed by the outside.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
static AsyncLocal<IUnitOfWork> _asyncUow = new AsyncLocal<IUnitOfWork>();
|
||||||
|
|
||||||
|
BaseEntity.Initialization(fsql, () => _asyncUow.Value);
|
||||||
|
```
|
||||||
|
|
||||||
|
At the beginning of `Scoped`: `_asyncUow.Value = fsql.CreateUnitOfWork();` (You can also use the `UnitOfWorkManager` object to get uow)
|
||||||
|
|
||||||
|
At the end of `Scoped`: `_asyncUow.Value = null;`
|
||||||
|
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using (var uow = fsql.CreateUnitOfWork())
|
||||||
|
{
|
||||||
|
_asyncUow.Value = uow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//todo ... BaseEntity internal CURD method keeps using uow transaction
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_asyncUow.Value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
uow.Commit();
|
||||||
|
}
|
||||||
|
```
|
@ -1,4 +1,6 @@
|
|||||||
# 前言
|
**中文** | [English](README.MD)
|
||||||
|
|
||||||
|
# 前言
|
||||||
|
|
||||||
尝试过 ado.net、dapper、ef,以及Repository仓储,甚至自己还写过生成器工具,以便做常规CRUD操作。
|
尝试过 ado.net、dapper、ef,以及Repository仓储,甚至自己还写过生成器工具,以便做常规CRUD操作。
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ public class UserGroup : BaseEntity<UserGroup, int>
|
|||||||
public string GroupName { get; set; }
|
public string GroupName { get; set; }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
> 有关更多实体的特性配置,请参考资料:https://github.com/2881099/FreeSql/wiki/%e5%ae%9e%e4%bd%93%e7%89%b9%e6%80%a7
|
> 有关更多实体的特性配置,请参考资料:https://github.com/dotnetcore/FreeSql/wiki/%e5%ae%9e%e4%bd%93%e7%89%b9%e6%80%a7
|
||||||
|
|
||||||
2、定义一个主键 Guid 的实体类型,保存数据时会自动产生有序不重复的 Guid 值(不用自己指定 Guid.NewGuid());
|
2、定义一个主键 Guid 的实体类型,保存数据时会自动产生有序不重复的 Guid 值(不用自己指定 Guid.NewGuid());
|
||||||
|
|
@ -1,13 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
namespace FreeSql.DataAnnotations
|
namespace FreeSql.DataAnnotations
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当实体类属性为【对象】时,以JSON形式映射存储
|
/// When the entity class property is <see cref="object"/>, map storage in JSON format. <br />
|
||||||
|
/// 当实体类属性为【对象】时,以 JSON 形式映射存储
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class JsonMapAttribute : Attribute
|
public class JsonMapAttribute : Attribute { }
|
||||||
{
|
}
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ using System.Collections.Concurrent;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
public static class FreeSqlJsonMapCoreExtensions
|
public static class FreeSqlJsonMapCoreExtensions
|
||||||
@ -19,11 +18,12 @@ public static class FreeSqlJsonMapCoreExtensions
|
|||||||
public static ColumnFluent JsonMap(this ColumnFluent col)
|
public static ColumnFluent JsonMap(this ColumnFluent col)
|
||||||
{
|
{
|
||||||
_dicJsonMapFluentApi.GetOrAdd(col._entityType, et => new ConcurrentDictionary<string, bool>())
|
_dicJsonMapFluentApi.GetOrAdd(col._entityType, et => new ConcurrentDictionary<string, bool>())
|
||||||
.GetOrAdd(col._property.Name, pn => true);
|
.GetOrAdd(col._property.Name, pn => true);
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// When the entity class property is <see cref="object"/> and the attribute is marked as <see cref="JsonMapAttribute"/>, map storage in JSON format. <br />
|
||||||
/// 当实体类属性为【对象】时,并且标记特性 [JsonMap] 时,该属性将以JSON形式映射存储
|
/// 当实体类属性为【对象】时,并且标记特性 [JsonMap] 时,该属性将以JSON形式映射存储
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@ -43,7 +43,7 @@ public static class FreeSqlJsonMapCoreExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
that.Aop.ConfigEntityProperty += new EventHandler<FreeSql.Aop.ConfigEntityPropertyEventArgs>((s, e) =>
|
that.Aop.ConfigEntityProperty += (s, e) =>
|
||||||
{
|
{
|
||||||
var isJsonMap = e.Property.GetCustomAttributes(typeof(JsonMapAttribute), false).Any() || _dicJsonMapFluentApi.TryGetValue(e.EntityType, out var tryjmfu) && tryjmfu.ContainsKey(e.Property.Name);
|
var isJsonMap = e.Property.GetCustomAttributes(typeof(JsonMapAttribute), false).Any() || _dicJsonMapFluentApi.TryGetValue(e.EntityType, out var tryjmfu) && tryjmfu.ContainsKey(e.Property.Name);
|
||||||
if (isJsonMap)
|
if (isJsonMap)
|
||||||
@ -61,7 +61,6 @@ public static class FreeSqlJsonMapCoreExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
Extensions/FreeSql.Extensions.JsonMap/README.MD
Normal file
25
Extensions/FreeSql.Extensions.JsonMap/README.MD
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[中文](README.zh-CN.MD) | **English**
|
||||||
|
|
||||||
|
FreeSql extension package, map *ValueObject* to `typeof(string)`, install the extension package:
|
||||||
|
|
||||||
|
> dotnet add package FreeSql.Extensions.JsonMap
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
fsql.UseJsonMap(); //Turn on function
|
||||||
|
|
||||||
|
class TestConfig
|
||||||
|
{
|
||||||
|
public int clicks { get; set; }
|
||||||
|
public string title { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Table(Name = "sysconfig")]
|
||||||
|
public class S_SysConfig<T>
|
||||||
|
{
|
||||||
|
[Column(IsPrimary = true)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonMap]
|
||||||
|
public T Config { get; set; }
|
||||||
|
}
|
||||||
|
```
|
@ -1,4 +1,6 @@
|
|||||||
FreeSql 扩展包,将值对象映射成 typeof(string),安装扩展包:
|
**中文** | [English](README.MD)
|
||||||
|
|
||||||
|
FreeSql 扩展包,将值对象映射成 `typeof(string)`,安装扩展包:
|
||||||
|
|
||||||
> dotnet add package FreeSql.Extensions.JsonMap
|
> dotnet add package FreeSql.Extensions.JsonMap
|
||||||
|
|
||||||
@ -20,4 +22,4 @@ public class S_SysConfig<T>
|
|||||||
[JsonMap]
|
[JsonMap]
|
||||||
public T Config { get; set; }
|
public T Config { get; set; }
|
||||||
}
|
}
|
||||||
```
|
```
|
@ -19,6 +19,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Colorful.Console" Version="1.2.9" />
|
<PackageReference Include="Colorful.Console" Version="1.2.9" />
|
||||||
<PackageReference Include="RazorEngine.NetCore" Version="2.2.6" />
|
<PackageReference Include="RazorEngine.NetCore" Version="2.2.6" />
|
||||||
|
<PackageReference Include="System.CodeDom" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -4,7 +4,10 @@ using FreeSql.DatabaseModel;
|
|||||||
using FreeSql.Internal.CommonProvider;
|
using FreeSql.Internal.CommonProvider;
|
||||||
using MySqlConnector;
|
using MySqlConnector;
|
||||||
using System;
|
using System;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@ -50,7 +53,17 @@ public class RazorModel
|
|||||||
if (text.Length <= 1) return text.ToLower();
|
if (text.Length <= 1) return text.ToLower();
|
||||||
else return text.Substring(0, 1).ToLower() + text.Substring(1, text.Length - 1);
|
else return text.Substring(0, 1).ToLower() + text.Substring(1, text.Length - 1);
|
||||||
}
|
}
|
||||||
|
private string LiteralString(string text)
|
||||||
|
{
|
||||||
|
using (var writer = new StringWriter())
|
||||||
|
{
|
||||||
|
using (var provider = CodeDomProvider.CreateProvider("CSharp"))
|
||||||
|
{
|
||||||
|
provider.GenerateCodeFromExpression(new CodePrimitiveExpression(text), writer, null);
|
||||||
|
return writer.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public string GetCsType(DbColumnInfo col)
|
public string GetCsType(DbColumnInfo col)
|
||||||
{
|
{
|
||||||
if (fsql.Ado.DataType == FreeSql.DataType.MySql)
|
if (fsql.Ado.DataType == FreeSql.DataType.MySql)
|
||||||
@ -250,10 +263,10 @@ public class RazorModel
|
|||||||
if (cstype == typeof(decimal)) return defval + "M";
|
if (cstype == typeof(decimal)) return defval + "M";
|
||||||
return defval;
|
return defval;
|
||||||
}
|
}
|
||||||
if (cstype == typeof(Guid) && Guid.TryParse(defval, out var tryguid)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"Guid.Parse(\"{defval.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")}\")";
|
if (cstype == typeof(Guid) && Guid.TryParse(defval, out var tryguid)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"Guid.Parse({LiteralString(defval)})";
|
||||||
if (cstype == typeof(DateTime) && DateTime.TryParse(defval, out var trydt)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"DateTime.Parse(\"{defval.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")}\")";
|
if (cstype == typeof(DateTime) && DateTime.TryParse(defval, out var trydt)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"DateTime.Parse({LiteralString(defval)})";
|
||||||
if (cstype == typeof(TimeSpan) && TimeSpan.TryParse(defval, out var tryts)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"TimeSpan.Parse(\"{defval.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")}\")";
|
if (cstype == typeof(TimeSpan) && TimeSpan.TryParse(defval, out var tryts)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"TimeSpan.Parse({LiteralString(defval)})";
|
||||||
if (cstype == typeof(string)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"\"{defval.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")}\"";
|
if (cstype == typeof(string)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : LiteralString(defval);
|
||||||
if (cstype == typeof(bool)) return isInsertValueSql ? defval : (defval == "1" || defval == "t" ? "true" : "false");
|
if (cstype == typeof(bool)) return isInsertValueSql ? defval : (defval == "1" || defval == "t" ? "true" : "false");
|
||||||
if (fsql.Ado.DataType == DataType.MySql || fsql.Ado.DataType == DataType.OdbcMySql)
|
if (fsql.Ado.DataType == DataType.MySql || fsql.Ado.DataType == DataType.OdbcMySql)
|
||||||
if (col.DbType == (int)MySqlDbType.Enum || col.DbType == (int)MySqlDbType.Set)
|
if (col.DbType == (int)MySqlDbType.Enum || col.DbType == (int)MySqlDbType.Set)
|
||||||
|
@ -171,8 +171,12 @@ namespace FreeSql
|
|||||||
if (string.IsNullOrEmpty(_masterConnectionString) && _connectionFactory == null) throw new Exception("参数 masterConnectionString 不可为空,请检查 UseConnectionString");
|
if (string.IsNullOrEmpty(_masterConnectionString) && _connectionFactory == null) throw new Exception("参数 masterConnectionString 不可为空,请检查 UseConnectionString");
|
||||||
IFreeSql<TMark> ret = null;
|
IFreeSql<TMark> ret = null;
|
||||||
var type = _providerType;
|
var type = _providerType;
|
||||||
if (type?.IsGenericType == true) type = type.MakeGenericType(typeof(TMark));
|
if (type != null)
|
||||||
if (type == null)
|
{
|
||||||
|
if (type.IsGenericTypeDefinition)
|
||||||
|
type = type.MakeGenericType(typeof(TMark));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Action<string, string> throwNotFind = (dll, providerType) => throw new Exception($"缺少 FreeSql 数据库实现包:{dll},可前往 nuget 下载;如果存在 {dll} 依然报错(原因是环境问题导致反射不到类型),请在 UseConnectionString/UseConnectionFactory 第三个参数手工传入 typeof({providerType})");
|
Action<string, string> throwNotFind = (dll, providerType) => throw new Exception($"缺少 FreeSql 数据库实现包:{dll},可前往 nuget 下载;如果存在 {dll} 依然报错(原因是环境问题导致反射不到类型),请在 UseConnectionString/UseConnectionFactory 第三个参数手工传入 typeof({providerType})");
|
||||||
switch (_dataType)
|
switch (_dataType)
|
||||||
|
@ -15,7 +15,7 @@ namespace FreeSql.MsAccess
|
|||||||
public override IDelete<T1> CreateDeleteProvider<T1>(object dywhere) => new MsAccessDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
public override IDelete<T1> CreateDeleteProvider<T1>(object dywhere) => new MsAccessDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||||
public override IInsertOrUpdate<T1> CreateInsertOrUpdateProvider<T1>() => throw new NotImplementedException();
|
public override IInsertOrUpdate<T1> CreateInsertOrUpdateProvider<T1>() => throw new NotImplementedException();
|
||||||
|
|
||||||
public override IDbFirst DbFirst => throw new NotImplementedException("FreeSql.Provider.Sqlite 未实现该功能");
|
public override IDbFirst DbFirst => throw new NotImplementedException("FreeSql.Provider.MsAccess 未实现该功能");
|
||||||
public MsAccessProvider(string masterConnectionString, string[] slaveConnectionString, Func<DbConnection> connectionFactory = null)
|
public MsAccessProvider(string masterConnectionString, string[] slaveConnectionString, Func<DbConnection> connectionFactory = null)
|
||||||
{
|
{
|
||||||
this.InternalCommonUtils = new MsAccessUtils(this);
|
this.InternalCommonUtils = new MsAccessUtils(this);
|
||||||
|
28
README.md
28
README.md
@ -5,7 +5,7 @@ FreeSql is a powerful O/RM component, supports .NET Core 2.1+, .NET Framework 4.
|
|||||||
[](https://github.com/dotnetcore)
|
[](https://github.com/dotnetcore)
|
||||||
[](https://www.nuget.org/packages/FreeSql)
|
[](https://www.nuget.org/packages/FreeSql)
|
||||||
[](https://www.nuget.org/stats/packages/FreeSql?groupby=Version)
|
[](https://www.nuget.org/stats/packages/FreeSql?groupby=Version)
|
||||||
[](https://raw.githubusercontent.com/2881099/FreeSql/master/LICENSE.txt)
|
[](https://raw.githubusercontent.com/dotnetcore/FreeSql/master/LICENSE.txt)
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<span>English</span> |
|
<span>English</span> |
|
||||||
@ -15,30 +15,30 @@ FreeSql is a powerful O/RM component, supports .NET Core 2.1+, .NET Framework 4.
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
- 🛠 Support CodeFirst data migration.
|
- 🛠 Support CodeFirst data migration.
|
||||||
- 💻 Support DbFirst import entity class from database, or use [Generation Tool](https://github.com/2881099/FreeSql/wiki/DbFirst).
|
- 💻 Support DbFirst import entity class from database, or use [Generation Tool](https://github.com/dotnetcore/FreeSql/wiki/DbFirst).
|
||||||
- ⛳ Support advanced type mapping, such as PostgreSQL array type, etc.
|
- ⛳ Support advanced type mapping, such as PostgreSQL array type, etc.
|
||||||
- 🌲 Support expression functions, and customizable analysis.
|
- 🌲 Support expression functions, and customizable analysis.
|
||||||
- 🏁 Support one-to-many and many-to-many navigation properties, include and lazy loading.
|
- 🏁 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 Read/Write separation, Splitting Table/Database, Global filters, Optimistic and pessimistic locker.
|
||||||
- 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/翰高/华为GaussDB/Access, etc.
|
- 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/Dameng/人大金仓/Shentong Database/翰高/HUAWEI GaussDB/Access, etc.
|
||||||
|
|
||||||
QQ Groups:4336577(full)、**8578575(full)**、**52508226(available)**
|
QQ Groups:4336577(full)、8578575(full)、**52508226(available)**
|
||||||
|
|
||||||
## 📚 Documentation
|
## 📚 Documentation
|
||||||
|
|
||||||
| |
|
| |
|
||||||
| - |
|
| - |
|
||||||
| [Get started](https://www.cnblogs.com/FreeSql/p/11531300.html) \| [Select](https://github.com/2881099/FreeSql/wiki/%e6%9f%a5%e8%af%a2) \| [Update](https://github.com/2881099/FreeSql/wiki/%e4%bf%ae%e6%94%b9) \| [Insert](https://github.com/2881099/FreeSql/wiki/%e6%b7%bb%e5%8a%a0) \| [Delete](https://github.com/2881099/FreeSql/wiki/%e5%88%a0%e9%99%a4) \| [FAQ](https://github.com/dotnetcore/FreeSql/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) |
|
| [Get started](https://www.cnblogs.com/FreeSql/p/11531300.html) \| [Select](https://github.com/dotnetcore/FreeSql/wiki/Query-Data) \| [Update](https://github.com/dotnetcore/FreeSql/wiki/Update-Data) \| [Insert](https://github.com/dotnetcore/FreeSql/wiki/Insert-Data) \| [Delete](https://github.com/dotnetcore/FreeSql/wiki/Delete-Data) \| [FAQ](https://github.com/dotnetcore/FreeSql/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) |
|
||||||
| [Expression](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0) \| [CodeFirst](https://github.com/2881099/FreeSql/wiki/CodeFirst) \| [DbFirst](https://github.com/2881099/FreeSql/wiki/DbFirst) \| [Filters](https://github.com/2881099/FreeSql/wiki/%e8%bf%87%e6%bb%a4%e5%99%a8) \| [AOP](https://github.com/2881099/FreeSql/wiki/AOP) |
|
| [Expression](https://github.com/dotnetcore/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0) \| [CodeFirst](https://github.com/dotnetcore/FreeSql/wiki/CodeFirst) \| [DbFirst](https://github.com/2881099/FreeSql/wiki/DbFirst) \| [Filters](https://github.com/dotnetcore/FreeSql/wiki/%e8%bf%87%e6%bb%a4%e5%99%a8) \| [AOP](https://github.com/2881099/FreeSql/wiki/AOP) |
|
||||||
| [Repository](https://github.com/2881099/FreeSql/wiki/Repository) \| [UnitOfWork](https://github.com/2881099/FreeSql/wiki/%e5%b7%a5%e4%bd%9c%e5%8d%95%e5%85%83) \| [DbContext](https://github.com/2881099/FreeSql/wiki/DbContext) \| [ADO](https://github.com/2881099/FreeSql/wiki/ADO) |
|
| [Repository](https://github.com/dotnetcore/FreeSql/wiki/Repository) \| [UnitOfWork](https://github.com/dotnetcore/FreeSql/wiki/%e5%b7%a5%e4%bd%9c%e5%8d%95%e5%85%83) \| [DbContext](https://github.com/dotnetcore/FreeSql/wiki/DbContext) \| [ADO](https://github.com/2881099/FreeSql/wiki/ADO) |
|
||||||
| [Read/Write](https://github.com/2881099/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb) \| [Splitting Table](https://github.com/2881099/FreeSql/wiki/%e5%88%86%e8%a1%a8%e5%88%86%e5%ba%93) \| [Hide tech](https://github.com/2881099/FreeSql/wiki/%E9%AA%9A%E6%93%8D%E4%BD%9C) \| [*Update Notes*](https://github.com/2881099/FreeSql/wiki/%e6%9b%b4%e6%96%b0%e6%97%a5%e5%bf%97) |
|
| [Read/Write](https://github.com/dotnetcore/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb) \| [Splitting Table](https://github.com/dotnetcore/FreeSql/wiki/%e5%88%86%e8%a1%a8%e5%88%86%e5%ba%93) \| [Hide tech](https://github.com/dotnetcore/FreeSql/wiki/%E9%AA%9A%E6%93%8D%E4%BD%9C) \| [*Update Notes*](https://github.com/dotnetcore/FreeSql/wiki/%e6%9b%b4%e6%96%b0%e6%97%a5%e5%bf%97) |
|
||||||
|
|
||||||
> Please select a development mode:
|
> Please select a development mode:
|
||||||
|
|
||||||
- Use FreeSql, keep the original usage.
|
- Use FreeSql, keep the original usage.
|
||||||
- Use [FreeSql.Repository](https://github.com/2881099/FreeSql/wiki/Repository), Repository + UnitOfWork.
|
- Use [FreeSql.Repository](https://github.com/dotnetcore/FreeSql/wiki/Repository), Repository + UnitOfWork.
|
||||||
- Use [FreeSql.DbContext](https://github.com/2881099/FreeSql/wiki/DbContext), Like efcore.
|
- Use [FreeSql.DbContext](https://github.com/dotnetcore/FreeSql/wiki/DbContext), Like efcore.
|
||||||
- Use [FreeSql.BaseEntity](https://github.com/2881099/FreeSql/tree/master/Examples/base_entity), Simple mode.
|
- Use [FreeSql.BaseEntity](https://github.com/dotnetcore/FreeSql/tree/master/Examples/base_entity), Simple mode.
|
||||||
|
|
||||||
> Some open source projects that use FreeSql:
|
> Some open source projects that use FreeSql:
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ fsql.Select<YourType>()
|
|||||||
.OrderByDescending(a => a.Id)
|
.OrderByDescending(a => a.Id)
|
||||||
.ToList()
|
.ToList()
|
||||||
```
|
```
|
||||||
[More..](https://github.com/2881099/FreeSql/wiki/%e6%9f%a5%e8%af%a2)
|
[More..](https://github.com/dotnetcore/FreeSql/wiki/%e6%9f%a5%e8%af%a2)
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
fsql.Select<Song>().Where(a => new[] { 1, 2, 3 }.Contains(a.Id)).ToList();
|
fsql.Select<Song>().Where(a => new[] { 1, 2, 3 }.Contains(a.Id)).ToList();
|
||||||
@ -122,7 +122,7 @@ fsql.Select<Song>().Where(a => a.CreateTime.Date == DateTime.Today).ToList();
|
|||||||
|
|
||||||
fsql.Select<Song>().OrderBy(a => Guid.NewGuid()).Limit(10).ToList();
|
fsql.Select<Song>().OrderBy(a => Guid.NewGuid()).Limit(10).ToList();
|
||||||
```
|
```
|
||||||
[More..](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0)
|
[More..](https://github.com/dotnetcore/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0)
|
||||||
|
|
||||||
### 🚁 Repository
|
### 🚁 Repository
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ Elapsed: 00:00:00.6707125; ToList Entity Counts: 131072; ORM: FreeSql*
|
|||||||
Elapsed: 00:00:00.6495301; Query Entity Counts: 131072; ORM: Dapper
|
Elapsed: 00:00:00.6495301; Query Entity Counts: 131072; ORM: Dapper
|
||||||
```
|
```
|
||||||
|
|
||||||
[More..](https://github.com/2881099/FreeSql/wiki/%e6%80%a7%e8%83%bd)
|
[More..](https://github.com/dotnetcore/FreeSql/wiki/%e6%80%a7%e8%83%bd)
|
||||||
|
|
||||||
## 👯 Contributors
|
## 👯 Contributors
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user