- 增加 FreeSql.DbContext OnModelCreating 虚方法,实现在 DbContext 使用 FluentApi;#4 - 移除 FreeSql.Extensions.EfCoreFluentApi,功能移至 FreeSql.DbContext;

This commit is contained in:
28810 2020-04-16 02:58:34 +08:00
parent 43e1529a83
commit 36759402cc
23 changed files with 418 additions and 575 deletions

View File

@ -42,12 +42,12 @@ namespace dbcontext_01.Controllers
repos2Song.Where(a => a.Id > 10).ToList();
//查询结果,进入 states
var song = new Song { };
var song = new Song { Title = "empty" };
repos2Song.Insert(song);
id = song.Id;
var adds = Enumerable.Range(0, 100)
.Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
.ToList();
//创建一堆无主键值
@ -72,17 +72,7 @@ namespace dbcontext_01.Controllers
var ctx = _songContext;
var tag = new Tag
{
Name = "testaddsublist",
Tags = new[] {
new Tag { Name = "sub1" },
new Tag { Name = "sub2" },
new Tag {
Name = "sub3",
Tags = new[] {
new Tag { Name = "sub3_01" }
}
}
}
Name = "testaddsublist"
};
ctx.Tags.Add(tag);
@ -91,17 +81,7 @@ namespace dbcontext_01.Controllers
var tagAsync = new Tag
{
Name = "testaddsublist",
Tags = new[] {
new Tag { Name = "sub1" },
new Tag { Name = "sub2" },
new Tag {
Name = "sub3",
Tags = new[] {
new Tag { Name = "sub3_01" }
}
}
}
Name = "testaddsublist"
};
await ctx.Tags.AddAsync(tagAsync);
@ -109,7 +89,7 @@ namespace dbcontext_01.Controllers
ctx.Songs.Select.Where(a => a.Id > 10).ToList();
//查询结果,进入 states
song = new Song { };
song = new Song { Title = "empty" };
//可插入的 song
ctx.Songs.Add(song);
@ -117,7 +97,7 @@ namespace dbcontext_01.Controllers
//因有自增类型立即开启事务执行SQL返回自增值
adds = Enumerable.Range(0, 100)
.Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
.ToList();
//创建一堆无主键值
@ -159,12 +139,12 @@ namespace dbcontext_01.Controllers
reposSong.Where(a => a.Id > 10).ToList();
//查询结果,进入 states
song = new Song { };
song = new Song { Title = "empty" };
reposSong.Insert(song);
id = song.Id;
adds = Enumerable.Range(0, 100)
.Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
.ToList();
//创建一堆无主键值
@ -193,12 +173,12 @@ namespace dbcontext_01.Controllers
using (ctx = new SongContext())
{
song = new Song { };
song = new Song { Title = "empty" };
await ctx.Songs.AddAsync(song);
id = song.Id;
adds = Enumerable.Range(0, 100)
.Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
.ToList();
await ctx.Songs.AddRangeAsync(adds);

View File

@ -5,56 +5,109 @@ using System.Collections.Generic;
namespace dbcontext_01
{
public class SongContext : DbContext
{
public SongContext() : base() { }
public SongContext(IFreeSql fsql) : base(fsql, null) { }
public DbSet<Song> Songs { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseFreeSql(Startup.Fsql);
//这里直接指定一个静态的 IFreeSql 对象即可,切勿重新 Build()
}
protected override void OnModelCreating(ICodeFirst codefirst)
{
codefirst.Entity<Song>(eb =>
{
eb.ToTable("tb_song");
eb.Ignore(a => a.Field1);
eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();
eb.Property(a => a.Url).HasMaxLength(100);
eb.Property(a => a.RowVersion).IsRowVersion();
eb.Property(a => a.CreateTime).HasDefaultValueSql("current_timestamp");
eb.HasKey(a => a.Id);
eb.HasIndex(a => new { a.Id, a.Title }).IsUnique().HasName("idx_xxx11");
//一对多、多对一
eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs);
//多对多
eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag));
});
codefirst.Entity<SongType>(eb =>
{
eb.HasMany(a => a.Songs).WithOne(a => a.Type).HasForeignKey(a => a.TypeId);
eb.HasData(new[]
{
new SongType
{
Id = 1,
Name = "流行",
Songs = new List<Song>(new[]
{
new Song{ Title = "真的爱你" },
new Song{ Title = "爱你一万年" },
})
},
new SongType
{
Id = 2,
Name = "乡村",
Songs = new List<Song>(new[]
{
new Song{ Title = "乡里乡亲" },
})
},
});
});
codefirst.SyncStructure<SongType>();
codefirst.SyncStructure<Song>();
}
}
public class SongType
{
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
public class Song
{
[Column(IsIdentity = true)]
public int Id { get; set; }
public DateTime? Create_time { get; set; }
public bool? Is_deleted { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public DateTime CreateTime { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public int TypeId { get; set; }
public SongType Type { get; set; }
public List<Tag> Tags { get; set; }
[Column(IsVersion = true)]
public long versionRow { get; set; }
public int Field1 { get; set; }
public long RowVersion { get; set; }
}
public class Song_tag
{
public int Song_id { get; set; }
public virtual Song Song { get; set; }
public Song Song { get; set; }
public int Tag_id { get; set; }
public virtual Tag Tag { get; set; }
public Tag Tag { get; set; }
}
public class Tag
{
[Column(IsIdentity = true)]
public int Id { get; set; }
public int? Parent_id { get; set; }
public virtual Tag Parent { get; set; }
public decimal? Ddd { get; set; }
public string Name { get; set; }
public virtual ICollection<Song> Songs { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public List<Song> Songs { get; set; }
}
}

View File

@ -16,57 +16,8 @@ namespace dbcontext_01
{
public class Program
{
public class Song
{
[Column(IsIdentity = true)]
public int Id { get; set; }
public string BigNumber { get; set; }
[Column(IsVersion = true)]//使用简单
public long versionRow { get; set; }
}
public class SongContext : DbContext
{
public DbSet<Song> Songs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseFreeSql(fsql);
}
}
static IFreeSql fsql;
public static void Main(string[] args)
{
var asse = typeof(FreeSql.Internal.ObjectPool.ObjectPool<>).Assembly;
fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\dd2.db;Pooling=true;Max Pool Size=10")
.UseAutoSyncStructure(true)
.UseLazyLoading(true)
.UseNoneCommandParameter(true)
.UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
.Build();
using (var ctx = new SongContext())
{
var song = new Song { BigNumber = "1000000000000000000" };
ctx.Songs.Add(song);
ctx.Songs.Update(song);
song.BigNumber = (BigInteger.Parse(song.BigNumber) + 1).ToString();
ctx.Songs.Update(song);
ctx.SaveChanges();
var sql = fsql.Update<Song>().SetSource(song).ToSql();
}
CreateWebHostBuilder(args).Build().Run();
}

View File

@ -27,7 +27,7 @@ namespace efcore_to_freesql
.UseAutoSyncStructure(true)
.Build();
FreeSql.Extensions.EfCoreFluentApi.ICodeFirstExtensions.Test(Fsql);
FreeSqlDbContextExtensions.EfCoreFluentApiTest(Fsql);
DBContexts.BaseDBContext.Fsql = Fsql;

View File

@ -10,7 +10,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.EfCoreFluentApi\FreeSql.Extensions.EfCoreFluentApi.csproj" />
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
</ItemGroup>

View File

@ -1,37 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>1.4.0-preview0415</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>YeXiangQin</Authors>
<Description>FreeSql 扩展包实现,使用 FluentApi 方式配置实体模型,使用习惯接近 EFCore方便过渡.</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageTags>FreeSql;ORM;FluentApi</PackageTags>
<PackageId>$(AssemblyName)</PackageId>
<PackageIcon>logo.png</PackageIcon>
<Title>$(AssemblyName)</Title>
<IsPackable>true</IsPackable>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
</PropertyGroup>
<ItemGroup>
<None Include="../../logo.png" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
<DocumentationFile>FreeSql.Extensions.EfCoreFluentApi.xml</DocumentationFile>
<WarningLevel>3</WarningLevel>
</PropertyGroup>
</Project>

View File

@ -1,15 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>FreeSql.Extensions.EfCoreFluentApi</name>
</assembly>
<members>
<member name="M:FreeSql.Extensions.EfCoreFluentApi.EfCoreTableFluent`1.HasData(System.Collections.Generic.IEnumerable{`0})">
<summary>
使用 Repository + EnableAddOrUpdateNavigateList + NoneParameter 方式插入种子数据
</summary>
<param name="data"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using FreeSql.DataAnnotations;
using FreeSql.Internal.CommonProvider;
namespace FreeSql.Extensions.EfCoreFluentApi
{
public static class ICodeFirstExtensions
{
public static ICodeFirst Entity<T>(this ICodeFirst codeFirst, Action<EfCoreTableFluent<T>> modelBuilder)
{
var cf = codeFirst as CodeFirstProvider;
codeFirst.ConfigEntity<T>(tf => modelBuilder(new EfCoreTableFluent<T>(cf._orm, tf)));
return codeFirst;
}
public static void Test(IFreeSql fsql)
{
var cf = fsql.CodeFirst;
cf.Entity<Song>(eb =>
{
eb.ToTable("tb_song");
eb.Ignore(a => a.Field1);
eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();
eb.Property(a => a.Url).HasMaxLength(100);
eb.Property(a => a.RowVersion).IsRowVersion();
eb.Property(a => a.CreateTime).HasDefaultValueSql("current_timestamp");
eb.HasKey(a => a.Id);
eb.HasIndex(a => a.Title).IsUnique().HasName("idx_xxx11");
//一对多、多对一
eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs);
//多对多
eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag));
});
cf.Entity<SongType>(eb =>
{
eb.HasMany(a => a.Songs).WithOne(a => a.Type).HasForeignKey(a => a.TypeId);
eb.HasData(new[]
{
new SongType
{
Id = 1,
Name = "流行",
Songs = new List<Song>(new[]
{
new Song{ Title = "真的爱你" },
new Song{ Title = "爱你一万年" },
})
},
new SongType
{
Id = 2,
Name = "乡村",
Songs = new List<Song>(new[]
{
new Song{ Title = "乡里乡亲" },
})
},
});
});
cf.SyncStructure<SongType>();
cf.SyncStructure<Song>();
}
public class SongType
{
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
public 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 int TypeId { get; set; }
public SongType Type { get; set; }
public List<Tag> Tags { get; set; }
public int Field1 { get; set; }
public long RowVersion { get; set; }
}
public 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; }
}
public class Tag
{
[Column(IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
}
}

View File

@ -1,103 +0,0 @@
FreeSql 原本的 FluentApi 方法名与特性名保持一致,所以使用理解成本较低(只需要了解一份);
这个扩展包目的,为了照顾熟悉 EfCore FluentApi 的开发者,使用习惯 95% 相似;
> dotnet add package FreeSql.Extensions.EfCoreFluentApi
## 以假乱真
```csharp
static void Test()
{
ICodeFirst cf = null;
cf.Entity<Song>(eb =>
{
eb.ToTable("tb_song");
eb.Ignore(a => a.Field1);
eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();
eb.Property(a => a.Url).HasMaxLength(100);
eb.Property(a => a.RowVersion).IsRowVersion();
eb.Property(a => a.CreateTime).HasDefaultValueSql("getdate()");
eb.HasKey(a => a.Id);
eb.HasIndex(a => a.Title).IsUnique().HasName("idx_xxx11");
//一对多、多对一
eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs);
//多对多
eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag));
});
cf.Entity<SongType>(eb =>
{
eb.HasMany(a => a.Songs).WithOne(a => a.Type).HasForeignKey(a => a.TypeId);
eb.HasData(new[]
{
new SongType
{
Id = 1,
Name = "流行",
Songs = new List<Song>(new[]
{
new Song{ Title = "真的爱你" },
new Song{ Title = "爱你一万年" },
})
},
new SongType
{
Id = 2,
Name = "乡村",
Songs = new List<Song>(new[]
{
new Song{ Title = "乡里乡亲" },
})
},
});
});
}
public class SongType
{
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
public 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 int TypeId { get; set; }
public SongType Type { get; set; }
public List<Tag> Tags { get; set; }
public int Field1 { get; set; }
public long RowVersion { get; set; }
}
public 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; }
}
public class Tag
{
[Column(IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
```

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Threading;
using FreeSql.Internal.Model;
namespace FreeSql
{
@ -71,18 +72,27 @@ namespace FreeSql
}
if (_ormScoped != null) InitPropSets();
}
protected virtual void OnConfiguring(DbContextOptionsBuilder builder) { }
protected virtual void OnConfiguring(DbContextOptionsBuilder options) { }
protected virtual void OnModelCreating(ICodeFirst codefirst) { }
#region Set
static ConcurrentDictionary<Type, PropertyInfo[]> _dicGetDbSetProps = new ConcurrentDictionary<Type, PropertyInfo[]>();
static ConcurrentDictionary<Type, NaviteTuple<PropertyInfo[], bool>> _dicGetDbSetProps = new ConcurrentDictionary<Type, NaviteTuple<PropertyInfo[], bool>>();
internal void InitPropSets()
{
var props = _dicGetDbSetProps.GetOrAdd(this.GetType(), tp =>
var thisType = this.GetType();
var dicval = _dicGetDbSetProps.GetOrAdd(thisType, tp =>
NaviteTuple.Create(
tp.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
.Where(a => a.PropertyType.IsGenericType &&
a.PropertyType == typeof(DbSet<>).MakeGenericType(a.PropertyType.GetGenericArguments()[0])).ToArray());
a.PropertyType == typeof(DbSet<>).MakeGenericType(a.PropertyType.GetGenericArguments()[0])).ToArray(),
false));
if (dicval.Item2 == false)
{
if (_dicGetDbSetProps.TryUpdate(thisType, NaviteTuple.Create(dicval.Item1, true), dicval))
OnModelCreating(OrmOriginal.CodeFirst);
}
foreach (var prop in props)
foreach (var prop in dicval.Item1)
{
var set = this.Set(prop.PropertyType.GetGenericArguments()[0]);

View File

@ -14,6 +14,10 @@ namespace FreeSql.Extensions.EfCoreFluentApi
_cf = tf;
}
/// <summary>
/// 使用 FreeSql FluentApi 方法,当 EFCore FluentApi 方法无法表示的时候使用
/// </summary>
/// <returns></returns>
public ColumnFluent Help() => _cf;
public EfCoreColumnFluent HasColumnName(string name)

View File

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using FreeSql;
using FreeSql.DataAnnotations;
using FreeSql.Extensions.EfCoreFluentApi;
using FreeSql.Internal.CommonProvider;
partial class FreeSqlDbContextExtensions
{
/// <summary>
/// EFCore 99% 相似的 FluentApi 扩展方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="codeFirst"></param>
/// <param name="modelBuilder"></param>
/// <returns></returns>
public static ICodeFirst Entity<T>(this ICodeFirst codeFirst, Action<EfCoreTableFluent<T>> modelBuilder)
{
var cf = codeFirst as CodeFirstProvider;
codeFirst.ConfigEntity<T>(tf => modelBuilder(new EfCoreTableFluent<T>(cf._orm, tf)));
return codeFirst;
}
public static void EfCoreFluentApiTest(IFreeSql fsql)
{
var cf = fsql.CodeFirst;
cf.Entity<Song>(eb =>
{
eb.ToTable("tb_song");
eb.Ignore(a => a.Field1);
eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();
eb.Property(a => a.Url).HasMaxLength(100);
eb.Property(a => a.RowVersion).IsRowVersion();
eb.Property(a => a.CreateTime).HasDefaultValueSql("current_timestamp");
eb.HasKey(a => a.Id);
eb.HasIndex(a => a.Title).IsUnique().HasName("idx_xxx11");
//一对多、多对一
eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs);
//多对多
eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag));
});
cf.Entity<SongType>(eb =>
{
eb.HasMany(a => a.Songs).WithOne(a => a.Type).HasForeignKey(a => a.TypeId);
eb.HasData(new[]
{
new SongType
{
Id = 1,
Name = "流行",
Songs = new List<Song>(new[]
{
new Song{ Title = "真的爱你" },
new Song{ Title = "爱你一万年" },
})
},
new SongType
{
Id = 2,
Name = "乡村",
Songs = new List<Song>(new[]
{
new Song{ Title = "乡里乡亲" },
})
},
});
});
cf.SyncStructure<SongType>();
cf.SyncStructure<Song>();
}
public class SongType
{
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
public 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 int TypeId { get; set; }
public SongType Type { get; set; }
public List<Tag> Tags { get; set; }
public int Field1 { get; set; }
public long RowVersion { get; set; }
}
public 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; }
}
public class Tag
{
[Column(IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
public List<Song> Songs { get; set; }
}
}

View File

@ -31,6 +31,10 @@ namespace FreeSql.Extensions.EfCoreFluentApi
public EfCoreColumnFluent Property<TProperty>(Expression<Func<T, TProperty>> property) => new EfCoreColumnFluent(_tf.Property(property));
public EfCoreColumnFluent Property(string property) => new EfCoreColumnFluent(_tf.Property(property));
/// <summary>
/// 使用 FreeSql FluentApi 方法,当 EFCore FluentApi 方法无法表示的时候使用
/// </summary>
/// <returns></returns>
public TableFluent<T> Help() => _tf;
#region HasKey

View File

@ -1,12 +1,12 @@
#if netcoreapp
using Microsoft.Extensions.DependencyInjection;
using FreeSql;
using System;
using System.Linq;
using System.Reflection;
namespace FreeSql
namespace Microsoft.Extensions.DependencyInjection
{
public static class DbContextDependencyInjection
public static class FreeSqlDbContextDependencyInjection
{
static IServiceCollection AddFreeDbContext(this IServiceCollection services, Type dbContextType, Action<DbContextOptionsBuilder> options)
{

View File

@ -3,7 +3,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
public static class FreeSqlDbContextExtensions
public static partial class FreeSqlDbContextExtensions
{
/// <summary>

View File

@ -162,6 +162,25 @@
</summary>
<param name="data"></param>
</member>
<member name="M:FreeSql.Extensions.EfCoreFluentApi.EfCoreColumnFluent.Help">
<summary>
使用 FreeSql FluentApi 方法,当 EFCore FluentApi 方法无法表示的时候使用
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.EfCoreFluentApi.EfCoreTableFluent`1.Help">
<summary>
使用 FreeSql FluentApi 方法,当 EFCore FluentApi 方法无法表示的时候使用
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.EfCoreFluentApi.EfCoreTableFluent`1.HasData(System.Collections.Generic.IEnumerable{`0})">
<summary>
使用 Repository + EnableAddOrUpdateNavigateList + NoneParameter 方式插入种子数据
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IRepositoryUnitOfWork.GetRepository``2(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
@ -302,6 +321,15 @@
例如20191121_214504_1
</summary>
</member>
<member name="M:FreeSqlDbContextExtensions.Entity``1(FreeSql.ICodeFirst,System.Action{FreeSql.Extensions.EfCoreFluentApi.EfCoreTableFluent{``0}})">
<summary>
EFCore 99% 相似的 FluentApi 扩展方法
</summary>
<typeparam name="T"></typeparam>
<param name="codeFirst"></param>
<param name="modelBuilder"></param>
<returns></returns>
</member>
<member name="M:FreeSqlDbContextExtensions.CreateDbContext(IFreeSql)">
<summary>
创建普通数据上下文档对象
@ -324,7 +352,7 @@
<param name="that"></param>
<param name="options"></param>
</member>
<member name="M:FreeSqlRepositoryExtensions.GetRepository``2(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<member name="M:FreeSqlDbContextExtensions.GetRepository``2(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
返回默认仓库类
</summary>
@ -334,7 +362,7 @@
<param name="filter">数据过滤 + 验证</param>
<returns></returns>
</member>
<member name="M:FreeSqlRepositoryExtensions.GetRepository``1(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<member name="M:FreeSqlDbContextExtensions.GetRepository``1(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
返回默认仓库类,适用联合主键的仓储类
</summary>
@ -343,7 +371,7 @@
<param name="filter">数据过滤 + 验证</param>
<returns></returns>
</member>
<member name="M:FreeSqlRepositoryExtensions.GetGuidRepository``1(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Func{System.String,System.String})">
<member name="M:FreeSqlDbContextExtensions.GetGuidRepository``1(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Func{System.String,System.String})">
<summary>
返回仓库类
</summary>
@ -353,7 +381,7 @@
<param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
<returns></returns>
</member>
<member name="M:FreeSqlRepositoryExtensions.CreateUnitOfWork(IFreeSql)">
<member name="M:FreeSqlDbContextExtensions.CreateUnitOfWork(IFreeSql)">
<summary>
创建基于仓储功能的工作单元,务必使用 using 包含使用
</summary>

View File

@ -1,11 +1,10 @@
#if netcoreapp
using Microsoft.Extensions.DependencyInjection;
using FreeSql;
using System;
using System.Linq;
using System.Reflection;
namespace FreeSql
namespace Microsoft.Extensions.DependencyInjection
{
public static class FreeSqlRepositoryDependencyInjection
{
@ -41,5 +40,4 @@ namespace FreeSql
}
}
}
#endif

View File

@ -3,7 +3,7 @@ using System;
using System.Linq;
using System.Linq.Expressions;
public static class FreeSqlRepositoryExtensions
partial class FreeSqlDbContextExtensions
{
/// <summary>

View File

@ -72,8 +72,6 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "FreeSql.Tests.VB", "FreeSql
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.MsAccess", "Providers\FreeSql.Provider.MsAccess\FreeSql.Provider.MsAccess.csproj", "{B397A761-F646-41CF-A160-AB6C05DAF2FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.EfCoreFluentApi", "Extensions\FreeSql.Extensions.EfCoreFluentApi\FreeSql.Extensions.EfCoreFluentApi.csproj", "{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.All", "FreeSql.All\FreeSql.All.csproj", "{933115AD-769C-4FBE-B000-2E8CF2292377}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.Linq", "Extensions\FreeSql.Extensions.Linq\FreeSql.Extensions.Linq.csproj", "{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}"
@ -438,18 +436,6 @@ Global
{B397A761-F646-41CF-A160-AB6C05DAF2FB}.Release|x64.Build.0 = Release|Any CPU
{B397A761-F646-41CF-A160-AB6C05DAF2FB}.Release|x86.ActiveCfg = Release|Any CPU
{B397A761-F646-41CF-A160-AB6C05DAF2FB}.Release|x86.Build.0 = Release|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Debug|x64.ActiveCfg = Debug|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Debug|x64.Build.0 = Debug|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Debug|x86.ActiveCfg = Debug|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Debug|x86.Build.0 = Debug|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Release|Any CPU.Build.0 = Release|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Release|x64.ActiveCfg = Release|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Release|x64.Build.0 = Release|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Release|x86.ActiveCfg = Release|Any CPU
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F}.Release|x86.Build.0 = Release|Any CPU
{933115AD-769C-4FBE-B000-2E8CF2292377}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{933115AD-769C-4FBE-B000-2E8CF2292377}.Debug|Any CPU.Build.0 = Debug|Any CPU
{933115AD-769C-4FBE-B000-2E8CF2292377}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -511,7 +497,6 @@ Global
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
{B397A761-F646-41CF-A160-AB6C05DAF2FB} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
{773D5B63-DE6E-46DB-AF16-6FB1C1352B3F} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
{57B3F5B0-D46A-4442-8EC6-9A9A784404B7} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
{E74D90E8-1CBC-4677-817B-1CA05AB97937} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
EndGlobalSection

View File

@ -3,7 +3,7 @@ using System;
using System.Threading;
[ExpressionCall]
public static class FreeSqlGlobalExpressionCall
public static class FreeSqlGlobalExpressionCallExtensions
{
public static ThreadLocal<ExpressionCallContext> expContext = new ThreadLocal<ExpressionCallContext>();

View File

@ -2305,6 +2305,137 @@
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{System.Data.Common.DbDataReader,System.Threading.Tasks.Task},System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询若使用读写分离查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
</summary>
<param name="readerHander"></param>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{System.Data.Common.DbDataReader,System.Threading.Tasks.Task},System.String,System.Object)">
<summary>
查询ExecuteReaderAsync(dr => {}, "select * from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询
</summary>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.String,System.Object)">
<summary>
查询ExecuteArrayAsync("select * from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询
</summary>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.String,System.Object)">
<summary>
查询ExecuteDataSetAsync("select * from user where age > ?age; select 2", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询
</summary>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.String,System.Object)">
<summary>
查询ExecuteDataTableAsync("select * from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
在【主库】执行
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.String,System.Object)">
<summary>
在【主库】执行ExecuteNonQueryAsync("delete from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
在【主库】执行
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.String,System.Object)">
<summary>
在【主库】执行ExecuteScalarAsync("select 1 from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``1(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
执行SQL返回对象集合QueryAsync&lt;User&gt;("select * from user where age > ?age", new SqlParameter { ParameterName = "age", Value = 25 })
</summary>
<typeparam name="T"></typeparam>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``1(System.String,System.Object)">
<summary>
执行SQL返回对象集合QueryAsync&lt;User&gt;("select * from user where age > ?age", new { age = 25 })
</summary>
<typeparam name="T"></typeparam>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``2(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
执行SQL返回对象集合Query&lt;User&gt;("select * from user where age > ?age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
</summary>
<typeparam name="T1"></typeparam>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``2(System.String,System.Object)">
<summary>
执行SQL返回对象集合Query&lt;User&gt;("select * from user where age > ?age; select * from address", new { age = 25 })
</summary>
<typeparam name="T1"></typeparam>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="E:FreeSql.IAop.ParseExpression">
<summary>
可自定义解析表达式
@ -2651,7 +2782,7 @@
</member>
<member name="M:FreeSql.ICodeFirst.ConfigEntity``1(System.Action{FreeSql.DataAnnotations.TableFluent{``0}})">
<summary>
在外部配置实体的特性
FreeSql FluentApi 配置实体,方法名与特性相同
</summary>
<typeparam name="T"></typeparam>
<param name="entity"></param>
@ -2659,7 +2790,7 @@
</member>
<member name="M:FreeSql.ICodeFirst.ConfigEntity(System.Type,System.Action{FreeSql.DataAnnotations.TableFluent})">
<summary>
在外部配置实体的特性
FreeSql FluentApi 配置实体,方法名与特性相同
</summary>
<param name="type"></param>
<param name="entity"></param>
@ -2667,7 +2798,7 @@
</member>
<member name="M:FreeSql.ICodeFirst.GetConfigEntity(System.Type)">
<summary>
获取在外部配置实体的特性
获取 FreeSql FluentApi 配置实体的元数据
</summary>
<param name="type"></param>
<returns>未使用ConfigEntity配置时返回null</returns>
@ -2825,6 +2956,12 @@
<param name="timeout">超时</param>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.GetAsync">
<summary>
获取资源
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
<summary>
使用完毕后,归还资源
@ -2895,6 +3032,12 @@
</summary>
<param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnGetAsync(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
</summary>
<param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
归还对象给对象池的时候触发
@ -3078,7 +3221,7 @@
BigApple -> bigapple
</summary>
</member>
<member name="M:FreeSqlGlobalExpressionCall.Between(System.DateTime,System.DateTime,System.DateTime)">
<member name="M:FreeSqlGlobalExpressionCallExtensions.Between(System.DateTime,System.DateTime,System.DateTime)">
<summary>
C# that >= between &amp;&amp; that &lt;= and<para></para>
SQL that BETWEEN between AND and
@ -3088,7 +3231,7 @@
<param name="and"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExpressionCall.BetweenEnd(System.DateTime,System.DateTime,System.DateTime)">
<member name="M:FreeSqlGlobalExpressionCallExtensions.BetweenEnd(System.DateTime,System.DateTime,System.DateTime)">
<summary>
注意:这个方法和 Between 有细微区别<para></para>
C# that >= start &amp;&amp; that &lt; end<para></para>
@ -3527,167 +3670,4 @@
</summary>
</member>
</members>
</doc>
<returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``5(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}})">
<summary>
使用 or 拼接两个 lambda 表达式
</summary>
<returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Or``5(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}})">
<summary>
使用 or 拼接两个 lambda 表达式
</summary>
<param name="exp1"></param>
<param name="condition">true 时生效</param>
<param name="exp2"></param>
<returns></returns>
</member>
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.Not``5(System.Linq.Expressions.Expression{System.Func{``0,``1,``2,``3,``4,System.Boolean}},System.Boolean)">
<summary>
将 lambda 表达式取反
</summary>
<param name="exp"></param>
<param name="condition">true 时生效</param>
<returns></returns>
</member>
<member name="M:FreeUtil.NewMongodbId">
<summary>
生成类似Mongodb的ObjectId有序、不重复Guid
</summary>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1">
<summary>
插入数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(``0)">
<summary>
插入数据,传入实体
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(``0[])">
<summary>
插入数据,传入实体数组
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.List{``0})">
<summary>
插入数据,传入实体集合
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.IEnumerable{``0})">
<summary>
插入数据,传入实体集合
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1">
<summary>
修改数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1(System.Object)">
<summary>
修改数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1">
<summary>
查询数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1(System.Object)">
<summary>
查询数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1">
<summary>
删除数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1(System.Object)">
<summary>
删除数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Transaction(System.Action)">
<summary>
开启事务不支持异步60秒未执行完成可能被其他线程事务自动提交
</summary>
<param name="handler">事务体 () => {}</param>
</member>
<member name="M:IFreeSql.Transaction(System.TimeSpan,System.Action)">
<summary>
开启事务(不支持异步)
</summary>
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
<param name="handler">事务体 () => {}</param>
</member>
<member name="M:IFreeSql.Transaction(System.Data.IsolationLevel,System.TimeSpan,System.Action)">
<summary>
开启事务(不支持异步)
</summary>
<param name="isolationLevel"></param>
<param name="handler">事务体 () => {}</param>
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
</member>
<member name="P:IFreeSql.Ado">
<summary>
数据库访问对象
</summary>
</member>
<member name="P:IFreeSql.Aop">
<summary>
所有拦截方法都在这里
</summary>
</member>
<member name="P:IFreeSql.CodeFirst">
<summary>
CodeFirst 模式开发相关方法
</summary>
</member>
<member name="P:IFreeSql.DbFirst">
<summary>
DbFirst 模式开发相关方法
</summary>
</member>
<member name="P:IFreeSql.GlobalFilter">
<summary>
全局过滤设置,可默认附加为 Select/Update/Delete 条件
</summary>
</member>
</members>
</doc>

View File

@ -86,21 +86,21 @@ namespace FreeSql
/// <returns></returns>
DbInfoResult GetDbInfo(Type type);
/// <summary>
/// 在外部配置实体的特性
/// FreeSql FluentApi 配置实体,方法名与特性相同
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity);
/// <summary>
/// 在外部配置实体的特性
/// FreeSql FluentApi 配置实体,方法名与特性相同
/// </summary>
/// <param name="type"></param>
/// <param name="entity"></param>
/// <returns></returns>
ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity);
/// <summary>
/// 获取在外部配置实体的特性
/// 获取 FreeSql FluentApi 配置实体的元数据
/// </summary>
/// <param name="type"></param>
/// <returns>未使用ConfigEntity配置时返回null</returns>