mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-08-01 17:35:58 +08:00
initial commit
This commit is contained in:
117
Examples/aspnetcore_transaction/Controllers/HomeController.cs
Normal file
117
Examples/aspnetcore_transaction/Controllers/HomeController.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace aspnetcore_transaction.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("")]
|
||||
public class HomeController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet("1")]
|
||||
//[Transactional]
|
||||
public async Task<object> Get([FromServices] BaseRepository<Song> repoSong, [FromServices] BaseRepository<Detail> repoDetail, [FromServices] SongRepository repoSong2,
|
||||
[FromServices] SongService serviceSong)
|
||||
{
|
||||
//repoSong.Insert(new Song());
|
||||
//repoDetail.Insert(new Detail());
|
||||
//repoSong2.Insert(new Song());
|
||||
|
||||
//serviceSong.Test1();
|
||||
await serviceSong.Test11();
|
||||
return "111";
|
||||
}
|
||||
|
||||
[HttpGet("2")]
|
||||
[Transactional]
|
||||
public async Task<object> GetAsync([FromServices] BaseRepository<Song> repoSong, [FromServices] BaseRepository<Detail> repoDetail, [FromServices] SongRepository repoSong2,
|
||||
[FromServices] SongService serviceSong)
|
||||
{
|
||||
await repoSong.InsertAsync(new Song());
|
||||
await repoDetail.InsertAsync(new Detail());
|
||||
return "111";
|
||||
}
|
||||
}
|
||||
|
||||
public class SongService
|
||||
{
|
||||
BaseRepository<Song> _repoSong;
|
||||
BaseRepository<Detail> _repoDetail;
|
||||
SongRepository _repoSong2;
|
||||
|
||||
public SongService(BaseRepository<Song> repoSong, BaseRepository<Detail> repoDetail, SongRepository repoSong2)
|
||||
{
|
||||
var tb = repoSong.Orm.CodeFirst.GetTableByEntity(typeof(Song));
|
||||
_repoSong = repoSong;
|
||||
_repoDetail = repoDetail;
|
||||
_repoSong2 = repoSong2;
|
||||
}
|
||||
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public void Test1()
|
||||
{
|
||||
_repoSong.Insert(new Song());
|
||||
_repoDetail.Insert(new Detail());
|
||||
_repoSong2.Insert(new Song());
|
||||
}
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public Task Test11()
|
||||
{
|
||||
return Task.Delay(TimeSpan.FromSeconds(1)).ContinueWith(t =>
|
||||
_repoSong.InsertAsync(new Song()));
|
||||
}
|
||||
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public async Task Test2()
|
||||
{
|
||||
await _repoSong.InsertAsync(new Song());
|
||||
await _repoDetail.InsertAsync(new Detail());
|
||||
await _repoSong2.InsertAsync(new Song());
|
||||
}
|
||||
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public async Task<object> Test3()
|
||||
{
|
||||
await _repoSong.InsertAsync(new Song());
|
||||
await _repoDetail.InsertAsync(new Detail());
|
||||
await _repoSong2.InsertAsync(new Song());
|
||||
return "123";
|
||||
}
|
||||
}
|
||||
|
||||
public class SongRepository : DefaultRepository<Song, int>
|
||||
{
|
||||
public SongRepository(UnitOfWorkManager uowm) : base(uowm?.Orm, uowm) { }
|
||||
}
|
||||
|
||||
[Description("123")]
|
||||
public class Song
|
||||
{
|
||||
/// <summary>
|
||||
/// 自增
|
||||
/// </summary>
|
||||
[Column(IsIdentity = true)]
|
||||
[Description("自增id")]
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
public class Detail
|
||||
{
|
||||
[Column(IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
public int SongId { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
35
Examples/aspnetcore_transaction/Domain/SongRepository.cs
Normal file
35
Examples/aspnetcore_transaction/Domain/SongRepository.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace aspnetcore_transaction.Domain
|
||||
{
|
||||
public class SongRepository : DefaultRepository<Song, int>
|
||||
{
|
||||
public SongRepository(UnitOfWorkManager uowm) : base(uowm?.Orm, uowm) { }
|
||||
}
|
||||
|
||||
[Description("123")]
|
||||
public class Song
|
||||
{
|
||||
/// <summary>
|
||||
/// 自增
|
||||
/// </summary>
|
||||
[Column(IsIdentity = true)]
|
||||
[Description("自增id")]
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
public class Detail
|
||||
{
|
||||
[Column(IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
public int SongId { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
3
Examples/aspnetcore_transaction/FodyWeavers.xml
Normal file
3
Examples/aspnetcore_transaction/FodyWeavers.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<Rougamo />
|
||||
</Weavers>
|
26
Examples/aspnetcore_transaction/FodyWeavers.xsd
Normal file
26
Examples/aspnetcore_transaction/FodyWeavers.xsd
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||
<xs:element name="Weavers">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Rougamo" minOccurs="0" maxOccurs="1" type="xs:anyType" />
|
||||
</xs:all>
|
||||
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
27
Examples/aspnetcore_transaction/Program.cs
Normal file
27
Examples/aspnetcore_transaction/Program.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace aspnetcore_transaction
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureLogging(loggerBuilder =>
|
||||
{
|
||||
loggerBuilder.SetMinimumLevel(LogLevel.Critical);
|
||||
//loggerBuilder.ClearProviders();
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:64375/",
|
||||
"sslPort": 44336
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"aspnetcore_transaction": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
||||
}
|
||||
}
|
||||
}
|
57
Examples/aspnetcore_transaction/Services/SongService.cs
Normal file
57
Examples/aspnetcore_transaction/Services/SongService.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using aspnetcore_transaction.Domain;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace aspnetcore_transaction.Services
|
||||
{
|
||||
public class SongService
|
||||
{
|
||||
BaseRepository<Song> _repoSong;
|
||||
BaseRepository<Detail> _repoDetail;
|
||||
SongRepository _repoSong2;
|
||||
|
||||
public SongService(BaseRepository<Song> repoSong, BaseRepository<Detail> repoDetail, SongRepository repoSong2)
|
||||
{
|
||||
var tb = repoSong.Orm.CodeFirst.GetTableByEntity(typeof(Song));
|
||||
_repoSong = repoSong;
|
||||
_repoDetail = repoDetail;
|
||||
_repoSong2 = repoSong2;
|
||||
}
|
||||
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public void Test1()
|
||||
{
|
||||
_repoSong.Insert(new Song());
|
||||
_repoDetail.Insert(new Detail());
|
||||
_repoSong2.Insert(new Song());
|
||||
}
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public Task Test11()
|
||||
{
|
||||
return Task.Delay(TimeSpan.FromSeconds(1)).ContinueWith(t =>
|
||||
_repoSong.InsertAsync(new Song()));
|
||||
}
|
||||
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public async Task Test2()
|
||||
{
|
||||
await _repoSong.InsertAsync(new Song());
|
||||
await _repoDetail.InsertAsync(new Detail());
|
||||
await _repoSong2.InsertAsync(new Song());
|
||||
}
|
||||
|
||||
[Transactional(Propagation = Propagation.Nested)] //sqlite 不能嵌套事务,会锁库的
|
||||
public async Task<object> Test3()
|
||||
{
|
||||
await _repoSong.InsertAsync(new Song());
|
||||
await _repoDetail.InsertAsync(new Detail());
|
||||
await _repoSong2.InsertAsync(new Song());
|
||||
return "123";
|
||||
}
|
||||
}
|
||||
}
|
72
Examples/aspnetcore_transaction/Startup.cs
Normal file
72
Examples/aspnetcore_transaction/Startup.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using aspnetcore_transaction.Controllers;
|
||||
using FreeSql;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace aspnetcore_transaction
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
Fsql = new FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=50;TrustServerCertificate=true")
|
||||
.UseAutoSyncStructure(true)
|
||||
//.UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
|
||||
.UseNoneCommandParameter(true)
|
||||
.Build();
|
||||
|
||||
//Fsql.Aop.TraceBefore += (_, e) => Trace.WriteLine($"----TraceBefore---{e.Identifier} {e.Operation}");
|
||||
Fsql.Aop.TraceAfter += (_, e) =>
|
||||
{
|
||||
//Trace.WriteLine($"----TraceAfter---{e.Identifier} {e.Operation} {e.Remark} {e.Exception?.Message} {e.ElapsedMilliseconds}ms\r\n");
|
||||
if (e.Exception != null && e.Exception.Message.StartsWith("【主库】状态不可用,等待后台检查程序恢复方可使用。") == false) Console.WriteLine(e.Exception.Message + " === " + Fsql.Ado.MasterPool.Statistics);
|
||||
};
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public static IFreeSql Fsql { get; private set; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
ThreadPool.SetMinThreads(1000, 1000);
|
||||
|
||||
services.AddControllersWithViews();
|
||||
|
||||
services.AddSingleton<IFreeSql>(Fsql);
|
||||
services.AddScoped<UnitOfWorkManager>();
|
||||
services.AddFreeRepository(null, typeof(Startup).Assembly);
|
||||
////批量注入
|
||||
//foreach (var repo in typeof(Startup).Assembly.GetTypes()
|
||||
// .Where(a => a.IsAbstract == false && typeof(IBaseRepository).IsAssignableFrom(a)))
|
||||
// services.AddScoped(repo);
|
||||
services.AddScoped<SongService>();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
Console.OutputEncoding = Encoding.GetEncoding("GB2312");
|
||||
Console.InputEncoding = Encoding.GetEncoding("GB2312");
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
TransactionalAttribute.SetServiceProvider(context.RequestServices);
|
||||
await next();
|
||||
});
|
||||
|
||||
app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(a => a.MapControllers());
|
||||
}
|
||||
}
|
||||
}
|
49
Examples/aspnetcore_transaction/TransactionalAttribute.cs
Normal file
49
Examples/aspnetcore_transaction/TransactionalAttribute.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Rougamo.Context;
|
||||
|
||||
namespace FreeSql
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class TransactionalAttribute : Rougamo.MoAttribute
|
||||
{
|
||||
public Propagation Propagation { get; set; } = Propagation.Required;
|
||||
public IsolationLevel IsolationLevel { get => m_IsolationLevel.Value; set => m_IsolationLevel = value; }
|
||||
IsolationLevel? m_IsolationLevel;
|
||||
|
||||
static AsyncLocal<IServiceProvider> m_ServiceProvider = new AsyncLocal<IServiceProvider>();
|
||||
public static void SetServiceProvider(IServiceProvider serviceProvider) => m_ServiceProvider.Value = serviceProvider;
|
||||
|
||||
IUnitOfWork _uow;
|
||||
public override void OnEntry(MethodContext context)
|
||||
{
|
||||
var uowManager = m_ServiceProvider.Value.GetService(typeof(UnitOfWorkManager)) as UnitOfWorkManager;
|
||||
_uow = uowManager.Begin(this.Propagation, this.m_IsolationLevel);
|
||||
}
|
||||
public override void OnExit(MethodContext context)
|
||||
{
|
||||
if (typeof(Task).IsAssignableFrom(context.RealReturnType))
|
||||
{
|
||||
((Task)context.ReturnValue).ContinueWith(t => _OnExit());
|
||||
return;
|
||||
}
|
||||
_OnExit();
|
||||
|
||||
void _OnExit()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context.Exception == null) _uow.Commit();
|
||||
else _uow.Rollback();
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
_uow.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>aspnetcore_transaction.xml</DocumentationFile>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<NoWarn>1701;1702;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FreeSql.DbContext" Version="3.2.802" />
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite" Version="3.2.802" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="1.1.1" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
18
Examples/aspnetcore_transaction/aspnetcore_transaction.xml
Normal file
18
Examples/aspnetcore_transaction/aspnetcore_transaction.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>aspnetcore_transaction</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="P:aspnetcore_transaction.Controllers.Song.Id">
|
||||
<summary>
|
||||
自增
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:aspnetcore_transaction.Domain.Song.Id">
|
||||
<summary>
|
||||
自增
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
BIN
Examples/aspnetcore_transaction/aspnetcore经典示范.zip
Normal file
BIN
Examples/aspnetcore_transaction/aspnetcore经典示范.zip
Normal file
Binary file not shown.
36
Examples/base_entity/AspNetRoleClaims/AspNetRoleClaims.cs
Normal file
36
Examples/base_entity/AspNetRoleClaims/AspNetRoleClaims.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 角色声明
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetRoleClaims
|
||||
{
|
||||
|
||||
[DisplayName("ID")]
|
||||
[JsonProperty, Column(IsPrimary = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DisplayName("角色ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string RoleId { get; set; }
|
||||
|
||||
[DisplayName("角色声明")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ClaimType { get; set; }
|
||||
|
||||
[DisplayName("值")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ClaimValue { get; set; }
|
||||
|
||||
[Navigate(nameof(RoleId))]
|
||||
public virtual AspNetRoles AspNetRoles { get; set; }
|
||||
|
||||
}
|
||||
}
|
39
Examples/base_entity/AspNetRoleClaims/AspNetRoles.cs
Normal file
39
Examples/base_entity/AspNetRoleClaims/AspNetRoles.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 角色定义
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetRoles
|
||||
{
|
||||
|
||||
[DisplayName("ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string Id { get; set; }
|
||||
|
||||
[DisplayName("角色")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DisplayName("标准化名称")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string NormalizedName { get; set; }
|
||||
|
||||
[DisplayName("并发票据")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ConcurrencyStamp { get; set; }
|
||||
|
||||
//导航属性
|
||||
[Navigate(nameof(AspNetUserRoles.RoleId))]
|
||||
[DisplayName("角色表")]
|
||||
public virtual List<AspNetUserRoles> AspNetUserRoless { get; set; }
|
||||
|
||||
}
|
||||
}
|
39
Examples/base_entity/AspNetRoleClaims/AspNetUserClaims.cs
Normal file
39
Examples/base_entity/AspNetRoleClaims/AspNetUserClaims.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 用户声明
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetUserClaims
|
||||
{
|
||||
|
||||
[DisplayName("ID")]
|
||||
[JsonProperty, Column(IsPrimary = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DisplayName("用户ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string UserId { get; set; }
|
||||
|
||||
[DisplayName("声明类型")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ClaimType { get; set; }
|
||||
|
||||
[DisplayName("值")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ClaimValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户
|
||||
/// </summary>
|
||||
[Navigate(nameof(UserId))]
|
||||
public virtual AspNetUsers AspNetUsers { get; set; }
|
||||
|
||||
}
|
||||
}
|
39
Examples/base_entity/AspNetRoleClaims/AspNetUserLogins.cs
Normal file
39
Examples/base_entity/AspNetRoleClaims/AspNetUserLogins.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 用户登录
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetUserLogins
|
||||
{
|
||||
|
||||
[DisplayName("外联登录")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string LoginProvider { get; set; }
|
||||
|
||||
[DisplayName("用户ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string UserId { get; set; }
|
||||
|
||||
[DisplayName("外联Key")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
[DisplayName("外联名称")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ProviderDisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户
|
||||
/// </summary>
|
||||
[Navigate(nameof(UserId))]
|
||||
public virtual AspNetUsers AspNetUsers { get; set; }
|
||||
|
||||
}
|
||||
}
|
45
Examples/base_entity/AspNetRoleClaims/AspNetUserRoles.cs
Normal file
45
Examples/base_entity/AspNetRoleClaims/AspNetUserRoles.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 角色表
|
||||
/// <para>存储向哪些用户分配哪些角色</para>
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetUserRoles
|
||||
{
|
||||
|
||||
[DisplayName("用户ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string UserId { get; set; }
|
||||
|
||||
[JsonProperty, Column(IsIgnore = true)]
|
||||
[DisplayName("用户")]
|
||||
public string UserName { get => roleName ?? (AspNetUserss?.UserName); set => userName = value; }
|
||||
string userName;
|
||||
|
||||
[DisplayName("角色ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string RoleId { get; set; }
|
||||
|
||||
[JsonProperty, Column(IsIgnore = true)]
|
||||
[DisplayName("角色名称")]
|
||||
public string RoleName { get => roleName ?? (AspNetRoless?.Name); set => roleName = value; }
|
||||
string roleName;
|
||||
|
||||
[DisplayName("角色定义")]
|
||||
[Navigate(nameof(RoleId))]
|
||||
public virtual AspNetRoles AspNetRoless { get; set; }
|
||||
|
||||
[DisplayName("用户表")]
|
||||
[Navigate(nameof(UserId))]
|
||||
public virtual AspNetUsers AspNetUserss { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
36
Examples/base_entity/AspNetRoleClaims/AspNetUserTokens.cs
Normal file
36
Examples/base_entity/AspNetRoleClaims/AspNetUserTokens.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 用户令牌
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetUserTokens
|
||||
{
|
||||
|
||||
[DisplayName("用户ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string UserId { get; set; }
|
||||
|
||||
[DisplayName("名称")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DisplayName("外部登录提供程序")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string LoginProvider { get; set; }
|
||||
|
||||
[DisplayName("值")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Value { get; set; }
|
||||
|
||||
[Navigate(nameof(UserId))]
|
||||
public virtual AspNetUsers AspNetUsers { get; set; }
|
||||
|
||||
}
|
||||
}
|
149
Examples/base_entity/AspNetRoleClaims/AspNetUsers.cs
Normal file
149
Examples/base_entity/AspNetRoleClaims/AspNetUsers.cs
Normal file
@ -0,0 +1,149 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 用户表
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class AspNetUsers
|
||||
{
|
||||
|
||||
[DisplayName("用户ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
[DisplayName("用户名")]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[JsonProperty, Column(IsIgnore = true)]
|
||||
[DisplayName("角色")]
|
||||
public string RoleName { get => roleName ?? (AspNetUserRoless != null ? string.Join(",", AspNetUserRoless?.Select(a => a.RoleName ?? a.RoleId).ToList()) : ""); set => roleName = value; }
|
||||
string roleName;
|
||||
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Email { get; set; }
|
||||
|
||||
[DisplayName("电话")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string PhoneNumber { get; set; }
|
||||
|
||||
[DisplayName("自定义名称")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DisplayName("自定义角色")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string UserRole { get; set; }
|
||||
|
||||
[DisplayName("密码哈希")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string PasswordHash { get; set; }
|
||||
|
||||
[DisplayName("电子邮件已确认")]
|
||||
[JsonProperty]
|
||||
public int EmailConfirmed { get; set; }
|
||||
|
||||
[DisplayName("电话号码已确认")]
|
||||
[JsonProperty]
|
||||
public int PhoneNumberConfirmed { get; set; }
|
||||
|
||||
[DisplayName("锁定结束")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string LockoutEnd { get; set; }
|
||||
|
||||
[DisplayName("启用双因素登录")]
|
||||
[JsonProperty]
|
||||
public int TwoFactorEnabled { get; set; }
|
||||
|
||||
[DisplayName("并发票据")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ConcurrencyStamp { get; set; }
|
||||
|
||||
[DisplayName("防伪印章")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string SecurityStamp { get; set; }
|
||||
|
||||
[DisplayName("标准化电子邮件")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string NormalizedEmail { get; set; }
|
||||
|
||||
[DisplayName("标准化用户名")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string NormalizedUserName { get; set; }
|
||||
|
||||
[DisplayName("启用锁定")]
|
||||
[JsonProperty]
|
||||
public int LockoutEnabled { get; set; }
|
||||
|
||||
[DisplayName("国家")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Country { get; set; }
|
||||
|
||||
[DisplayName("省")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Province { get; set; }
|
||||
|
||||
[DisplayName("城市")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string City { get; set; }
|
||||
|
||||
[DisplayName("县")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string County { get; set; }
|
||||
|
||||
[DisplayName("邮编")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Zip { get; set; }
|
||||
|
||||
[DisplayName("街道")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Street { get; set; }
|
||||
|
||||
[DisplayName("税号")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string TaxNumber { get; set; }
|
||||
|
||||
[DisplayName("提供者")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string provider { get; set; }
|
||||
|
||||
[DisplayName("UUID")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string UUID { get; set; }
|
||||
|
||||
[DisplayName("生日")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string DOB { get; set; }
|
||||
|
||||
[DisplayName("访问失败次数")]
|
||||
[JsonProperty]
|
||||
public int AccessFailedCount { get; set; }
|
||||
|
||||
//导航属性
|
||||
[Navigate(nameof(AspNetUserRoles.UserId))]
|
||||
[DisplayName("角色表")]
|
||||
public virtual List<AspNetUserRoles> AspNetUserRoless { get; set; }
|
||||
|
||||
[Navigate(nameof(AspNetUserClaims.UserId))]
|
||||
[DisplayName("用户声明")]
|
||||
public virtual List<AspNetUserClaims> AspNetUserClaimss { get; set; }
|
||||
|
||||
[Navigate(nameof(AspNetUserLogins.UserId))]
|
||||
[DisplayName("用户登录")]
|
||||
public virtual List<AspNetUserLogins> AspNetUserLoginss { get; set; }
|
||||
|
||||
[JsonProperty, Column(IsIgnore = true)]
|
||||
[DisplayName("1st角色")]
|
||||
public string RoleName1st { get => roleName1st ?? ((AspNetUserRoless != null && AspNetUserRoless.Any()) ? AspNetUserRoless?.Select(a => a.RoleName ?? a.RoleId ?? "").First() : ""); set => roleName1st = value; }
|
||||
string roleName1st;
|
||||
|
||||
}
|
||||
}
|
53
Examples/base_entity/AspNetRoleClaims/DeviceCodes.cs
Normal file
53
Examples/base_entity/AspNetRoleClaims/DeviceCodes.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备代码
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class DeviceCodes
|
||||
{
|
||||
|
||||
[Display(Name = "用户代码")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string UserCode { get; set; }
|
||||
|
||||
[Display(Name = "设备代码")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string DeviceCode { get; set; }
|
||||
|
||||
[Display(Name = "主题编号")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string SubjectId { get; set; }
|
||||
|
||||
[Display(Name = "会话编号")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string SessionId { get; set; }
|
||||
|
||||
[Display(Name = "客户编号")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string ClientId { get; set; }
|
||||
|
||||
[Display(Name = "描述")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Display(Name = "创建时间")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string CreationTime { get; set; }
|
||||
|
||||
[Display(Name = "到期")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Expiration { get; set; }
|
||||
|
||||
[DisplayName("数据")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Data { get; set; }
|
||||
|
||||
}
|
||||
}
|
49
Examples/base_entity/AspNetRoleClaims/Keys.cs
Normal file
49
Examples/base_entity/AspNetRoleClaims/Keys.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 密钥
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class Keys
|
||||
{
|
||||
|
||||
[DisplayName("ID")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string Id { get; set; }
|
||||
|
||||
[DisplayName("版本")]
|
||||
[JsonProperty]
|
||||
public int Version { get; set; }
|
||||
|
||||
[DisplayName("创建")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Created { get; set; }
|
||||
|
||||
[DisplayName("使用")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Use { get; set; }
|
||||
|
||||
[DisplayName("算法")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Algorithm { get; set; }
|
||||
|
||||
[DisplayName("是X509证书")]
|
||||
[JsonProperty]
|
||||
public int IsX509Certificate { get; set; }
|
||||
|
||||
[DisplayName("数据保护")]
|
||||
[JsonProperty]
|
||||
public int DataProtected { get; set; }
|
||||
|
||||
[DisplayName("数据")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Data { get; set; }
|
||||
|
||||
}
|
||||
}
|
57
Examples/base_entity/AspNetRoleClaims/PersistedGrants.cs
Normal file
57
Examples/base_entity/AspNetRoleClaims/PersistedGrants.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
#nullable disable
|
||||
|
||||
namespace Densen.Models.ids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 持久化保存
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn), Table(DisableSyncStructure = true)]
|
||||
public partial class PersistedGrants
|
||||
{
|
||||
|
||||
[DisplayName("键值")]
|
||||
[JsonProperty, Column(StringLength = -2, IsPrimary = true, IsNullable = false)]
|
||||
public string Key { get; set; }
|
||||
|
||||
[DisplayName("类型")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Type { get; set; }
|
||||
|
||||
[DisplayName("主题编号")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string SubjectId { get; set; }
|
||||
|
||||
[DisplayName("会话编号")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string SessionId { get; set; }
|
||||
|
||||
[DisplayName("客户编号")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string ClientId { get; set; }
|
||||
|
||||
[DisplayName("描述")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[DisplayName("创建时间")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string CreationTime { get; set; }
|
||||
|
||||
[DisplayName("到期")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string Expiration { get; set; }
|
||||
|
||||
[DisplayName("消耗时间")]
|
||||
[JsonProperty, Column(StringLength = -2)]
|
||||
public string ConsumedTime { get; set; }
|
||||
|
||||
[DisplayName("数据")]
|
||||
[JsonProperty, Column(StringLength = -2, IsNullable = false)]
|
||||
public string Data { get; set; }
|
||||
|
||||
}
|
||||
}
|
53
Examples/base_entity/AspNetRoleClaims/WebAppIdentityUser.cs
Normal file
53
Examples/base_entity/AspNetRoleClaims/WebAppIdentityUser.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Densen.Identity.Models
|
||||
{
|
||||
|
||||
public class WebAppIdentityUser
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Full name
|
||||
/// </summary>
|
||||
[Display(Name = "全名")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Birth Date
|
||||
/// </summary>
|
||||
[Display(Name = "生日")]
|
||||
public DateTime? DOB { get; set; }
|
||||
|
||||
[Display(Name = "识别码")]
|
||||
public string? UUID { get; set; }
|
||||
|
||||
[Display(Name = "外联")]
|
||||
public string? provider { get; set; }
|
||||
|
||||
[Display(Name = "税号")]
|
||||
public string? TaxNumber { get; set; }
|
||||
|
||||
[Display(Name = "街道地址")]
|
||||
public string? Street { get; set; }
|
||||
|
||||
[Display(Name = "邮编")]
|
||||
public string? Zip { get; set; }
|
||||
|
||||
[Display(Name = "县")]
|
||||
public string? County { get; set; }
|
||||
|
||||
[Display(Name = "城市")]
|
||||
public string? City { get; set; }
|
||||
|
||||
[Display(Name = "省份")]
|
||||
public string? Province { get; set; }
|
||||
|
||||
[Display(Name = "国家")]
|
||||
public string? Country { get; set; }
|
||||
|
||||
[Display(Name = "类型")]
|
||||
public string? UserRole { get; set; }
|
||||
}
|
||||
}
|
BIN
Examples/base_entity/AspNetRoleClaims/ids_api.db
Normal file
BIN
Examples/base_entity/AspNetRoleClaims/ids_api.db
Normal file
Binary file not shown.
79
Examples/base_entity/Entities/User.cs
Normal file
79
Examples/base_entity/Entities/User.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
public class UserGroup : BaseEntity<UserGroup, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 组名
|
||||
/// </summary>
|
||||
public string GroupName { get; set; }
|
||||
|
||||
public List<User1> User1s { get; set; }
|
||||
}
|
||||
|
||||
public class Role : BaseEntity<Role, string>
|
||||
{
|
||||
public List<User1> User1s { get; set; }
|
||||
}
|
||||
public class RoleUser1 : BaseEntity<RoleUser1>
|
||||
{
|
||||
public string RoleId { get; set; }
|
||||
public Guid User1Id { get; set; }
|
||||
|
||||
public Role Role { get; set; }
|
||||
public User1 User1 { get; set; }
|
||||
}
|
||||
|
||||
public class IdentityUser1
|
||||
{
|
||||
[Column(IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
[MaxLength(32)]
|
||||
public string Username { get; set; }
|
||||
[MaxLength(64), Column(InsertValueSql = "'defaultname'")]
|
||||
public string Nickname { get; set; }
|
||||
}
|
||||
|
||||
public class User1 : BaseEntity<User1, Guid>
|
||||
{
|
||||
public int GroupId { get; set; }
|
||||
public UserGroup Group { get; set; }
|
||||
|
||||
public string[] Tags { get; set; }
|
||||
public virtual List<Role> Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 登陆名
|
||||
/// </summary>
|
||||
[MaxLength(32)]
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 昵称
|
||||
/// </summary>
|
||||
[MaxLength(64)]
|
||||
public string Nickname { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 头像
|
||||
/// </summary>
|
||||
[MaxLength(1024)]
|
||||
public string Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
[MaxLength(2000)]
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
||||
public class IdentityTable
|
||||
{
|
||||
[Column(IsIdentity = true, IsPrimary = true)]
|
||||
public int id { get; set; }
|
||||
|
||||
public string name { get; set; }
|
||||
}
|
104
Examples/base_entity/MessagePackMap.cs
Normal file
104
Examples/base_entity/MessagePackMap.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
class MessagePackMapInfo
|
||||
{
|
||||
public Guid id { get; set; }
|
||||
[MessagePackMap]
|
||||
public MessagePackMap01 Info { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class MessagePackMap01
|
||||
{
|
||||
[Key(0)]
|
||||
public string name { get; set; }
|
||||
[Key(1)]
|
||||
public string address { get;set; }
|
||||
}
|
||||
|
||||
namespace FreeSql.DataAnnotations
|
||||
{
|
||||
public class MessagePackMapAttribute : Attribute { }
|
||||
}
|
||||
|
||||
public static class FreeSqlMessagePackMapCoreExtensions
|
||||
{
|
||||
internal static int _isAoped = 0;
|
||||
static ConcurrentDictionary<Type, bool> _dicTypes = new ConcurrentDictionary<Type, bool>();
|
||||
static MethodInfo MethodMessagePackSerializerDeserialize = typeof(MessagePackSerializer).GetMethod("Deserialize", new[] { typeof(Type), typeof(ReadOnlyMemory<byte>), typeof(MessagePackSerializerOptions), typeof(CancellationToken) });
|
||||
static MethodInfo MethodMessagePackSerializerSerialize = typeof(MessagePackSerializer).GetMethod("Serialize", new[] { typeof(Type), typeof(object), typeof(MessagePackSerializerOptions), typeof(CancellationToken) });
|
||||
static ConcurrentDictionary<Type, ConcurrentDictionary<string, bool>> _dicMessagePackMapFluentApi = new ConcurrentDictionary<Type, ConcurrentDictionary<string, bool>>();
|
||||
static object _concurrentObj = new object();
|
||||
|
||||
public static ColumnFluent MessagePackMap(this ColumnFluent col)
|
||||
{
|
||||
_dicMessagePackMapFluentApi.GetOrAdd(col._entityType, et => new ConcurrentDictionary<string, bool>())
|
||||
.GetOrAdd(col._property.Name, pn => true);
|
||||
return col;
|
||||
}
|
||||
|
||||
public static void UseMessagePackMap(this IFreeSql that)
|
||||
{
|
||||
UseMessagePackMap(that, MessagePackSerializerOptions.Standard);
|
||||
}
|
||||
|
||||
public static void UseMessagePackMap(this IFreeSql that, MessagePackSerializerOptions settings)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _isAoped, 1, 0) == 0)
|
||||
{
|
||||
FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, Type type) =>
|
||||
{
|
||||
if (_dicTypes.ContainsKey(type))
|
||||
return Expression.IfThenElse(
|
||||
Expression.TypeIs(valueExp, type),
|
||||
Expression.Return(returnTarget, valueExp),
|
||||
Expression.Return(returnTarget, Expression.TypeAs(
|
||||
Expression.Call(MethodMessagePackSerializerDeserialize,
|
||||
Expression.Constant(type),
|
||||
Expression.New(typeof(ReadOnlyMemory<byte>).GetConstructor(new[] { typeof(byte[]) }), Expression.Convert(valueExp, typeof(byte[]))),
|
||||
Expression.Constant(settings, typeof(MessagePackSerializerOptions)),
|
||||
Expression.Constant(default(CancellationToken), typeof(CancellationToken)))
|
||||
, type))
|
||||
);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
that.Aop.ConfigEntityProperty += (s, e) =>
|
||||
{
|
||||
var isMessagePackMap = e.Property.GetCustomAttributes(typeof(MessagePackMapAttribute), false).Any() || _dicMessagePackMapFluentApi.TryGetValue(e.EntityType, out var tryjmfu) && tryjmfu.ContainsKey(e.Property.Name);
|
||||
if (isMessagePackMap)
|
||||
{
|
||||
e.ModifyResult.MapType = typeof(byte[]);
|
||||
e.ModifyResult.StringLength = -2;
|
||||
if (_dicTypes.TryAdd(e.Property.PropertyType, true))
|
||||
{
|
||||
lock (_concurrentObj)
|
||||
{
|
||||
FreeSql.Internal.Utils.dicExecuteArrayRowReadClassOrTuple[e.Property.PropertyType] = true;
|
||||
FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionObjectToBytesIfThenElse.Add((LabelTarget returnTarget, Expression valueExp, Expression elseExp, Type type) =>
|
||||
{
|
||||
return Expression.IfThenElse(
|
||||
Expression.TypeIs(valueExp, e.Property.PropertyType),
|
||||
Expression.Return(returnTarget,
|
||||
Expression.Call(MethodMessagePackSerializerSerialize,
|
||||
Expression.Constant(e.Property.PropertyType, typeof(Type)),
|
||||
Expression.Convert(valueExp, typeof(object)),
|
||||
Expression.Constant(settings, typeof(MessagePackSerializerOptions)),
|
||||
Expression.Constant(default(CancellationToken), typeof(CancellationToken)))
|
||||
, typeof(object)),
|
||||
elseExp);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
54
Examples/base_entity/ModAsTableImpl.cs
Normal file
54
Examples/base_entity/ModAsTableImpl.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class ModAsTableImpl : IAsTable
|
||||
{
|
||||
public ModAsTableImpl(IFreeSql fsql)
|
||||
{
|
||||
AllTables = Enumerable.Range(0, 9).Select(a => $"order_{a}").ToArray();
|
||||
fsql.Aop.CommandBefore += (_, e) =>
|
||||
{
|
||||
e.Command.CommandText = Regex.Replace(e.Command.CommandText, @"/\*astable\([^\)]+\)*\/", "1=1");
|
||||
};
|
||||
}
|
||||
|
||||
public string[] AllTables { get; }
|
||||
|
||||
public string GetTableNameByColumnValue(object columnValue, bool autoExpand = false)
|
||||
{
|
||||
var modid = (int)columnValue;
|
||||
return $"order_{(modid % 10)}";
|
||||
}
|
||||
|
||||
public string[] GetTableNamesByColumnValueRange(object columnValue1, object columnValue2)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsTableTableNameRangeResult GetTableNamesBySqlWhere(string sqlWhere, List<DbParameter> dbParams, SelectTableInfo tb, CommonUtils commonUtils)
|
||||
{
|
||||
var match = Regex.Match(sqlWhere, @"/\*astable\([^\)]+\)*\/");
|
||||
if (match.Success == false) return new IAsTableTableNameRangeResult(AllTables, null, null);
|
||||
var tables = match.Groups[1].Value.Split(',').Where(a => AllTables.Contains(a)).ToArray();
|
||||
if (tables.Any() == false) return new IAsTableTableNameRangeResult(AllTables, null, null);
|
||||
return new IAsTableTableNameRangeResult(tables, null, null);
|
||||
}
|
||||
|
||||
public IAsTable SetDefaultAllTables(Func<string[], string[]> audit)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public IAsTable SetTableName(int index, string tableName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
3312
Examples/base_entity/Program.cs
Normal file
3312
Examples/base_entity/Program.cs
Normal file
File diff suppressed because one or more lines are too long
52
Examples/base_entity/Test01/Role.cs
Normal file
52
Examples/base_entity/Test01/Role.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql;
|
||||
|
||||
namespace EMSServerModel.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD><C9AB>
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public partial class Role : BaseEntity<Role>{
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[JsonProperty, Column(IsPrimary = true, IsIdentity = true)]
|
||||
public long RoleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string RoleName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string RoleDesc { get; set; } = string.Empty;
|
||||
|
||||
///// <summary>
|
||||
///// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
||||
///// </summary>
|
||||
//[JsonProperty, Column(DbType = "date")]
|
||||
//public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public bool IsEnable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>Զർ<D4B6><E0B5BC>
|
||||
/// </summary>
|
||||
[Navigate(ManyToMany = typeof(UserRole))]
|
||||
public virtual ICollection<User> Users { get; protected set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
157
Examples/base_entity/Test01/User.cs
Normal file
157
Examples/base_entity/Test01/User.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using FreeSql.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using FreeSql;
|
||||
|
||||
namespace EMSServerModel.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户表bb123123
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public partial class User : BaseEntity<User> {
|
||||
|
||||
//[JsonProperty, Column(IsIdentity = true)]
|
||||
//public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编号
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)", IsPrimary = true)]
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 头像
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string Avatar { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 姓名
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 艺名
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string NickName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 电话
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string Tel { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 性别
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public Sex Sex { get; set; } = Sex.男;
|
||||
|
||||
/// <summary>
|
||||
/// 证件号
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string UID { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 生日
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "date")]
|
||||
public DateTime? DateOfBirth { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 出生地
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string PlaceOfBirth { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 居住地
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string Addr { get; set; } = string.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string Pwd { get; set; } = string.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 部门编号
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public long? DeptId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 职务编号
|
||||
/// </summary>
|
||||
[JsonProperty, Column(IsNullable = true)]
|
||||
public long TitleId { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
public long TitleId2 { get; set; }
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 创建时间
|
||||
///// </summary>
|
||||
//[JsonProperty, Column(DbType = "date")]
|
||||
//public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 国籍
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string Nationality { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 经手人
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string Handler { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 启用
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public bool IsEnable { get; set; } = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(100)")]
|
||||
public string Memos { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Navigate(ManyToMany = typeof(UserRole))]
|
||||
public virtual ICollection<Role> Roles { get; protected set; }
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 性别枚举
|
||||
/// </summary>
|
||||
public enum Sex
|
||||
{
|
||||
/// <summary>
|
||||
/// 女=0
|
||||
/// </summary>
|
||||
女=0,
|
||||
/// <summary>
|
||||
/// 男=1
|
||||
/// </summary>
|
||||
男=1
|
||||
}
|
||||
|
||||
}
|
36
Examples/base_entity/Test01/UserRole.cs
Normal file
36
Examples/base_entity/Test01/UserRole.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Newtonsoft.Json;
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql;
|
||||
|
||||
namespace EMSServerModel.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// <20>û<EFBFBD><C3BB><EFBFBD>ɫ<EFBFBD><C9AB>ϵ<EFBFBD><CFB5>aa111
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public partial class UserRole : BaseEntity<UserRole>{
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>1
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public long RoleId { get; set; }
|
||||
/// <summary>
|
||||
/// <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[Navigate("RoleId")]
|
||||
public Role Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string UserId { get; set; }
|
||||
/// <summary>
|
||||
/// <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[Navigate("UserId")]
|
||||
public User Users { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
52
Examples/base_entity/base_entity.csproj
Normal file
52
Examples/base_entity/base_entity.csproj
Normal file
@ -0,0 +1,52 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>base_entity.xml</DocumentationFile>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<NoWarn>1701;1702;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Confluent.Kafka" Version="2.2.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Npgsql.NetTopologySuite" Version="6.0.4" />
|
||||
<PackageReference Include="MessagePack" Version="2.4.35" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.AggregateRoot\FreeSql.Extensions.AggregateRoot.csproj" />
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.BaseEntity\FreeSql.Extensions.BaseEntity.csproj" />
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.JsonMap\FreeSql.Extensions.JsonMap.csproj" />
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" />
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.Linq\FreeSql.Extensions.Linq.csproj" />
|
||||
<ProjectReference Include="..\..\FreeSql.Repository\FreeSql.Repository.csproj" />
|
||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.ClickHouse\FreeSql.Provider.ClickHouse.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Firebird\FreeSql.Provider.Firebird.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Odbc\FreeSql.Provider.Odbc.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.QuestDb\FreeSql.Provider.QuestDb.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqliteCore\FreeSql.Provider.SqliteCore.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Xugu\FreeSql.Provider.Xugu.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="DmProvider">
|
||||
<HintPath>..\..\Providers\FreeSql.Provider.Dameng\lib\DmProvider\netstandard2.0\DmProvider.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="XuguClient">
|
||||
<HintPath>..\..\Providers\FreeSql.Provider.Xugu\lib\XuguClient\netstandard2.0\XuguClient.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
500
Examples/base_entity/base_entity.xml
Normal file
500
Examples/base_entity/base_entity.xml
Normal file
@ -0,0 +1,500 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>base_entity</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Densen.Models.ids.AspNetRoleClaims">
|
||||
<summary>
|
||||
角色声明
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.AspNetRoles">
|
||||
<summary>
|
||||
角色定义
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.AspNetUserClaims">
|
||||
<summary>
|
||||
用户声明
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Densen.Models.ids.AspNetUserClaims.AspNetUsers">
|
||||
<summary>
|
||||
用户
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.AspNetUserLogins">
|
||||
<summary>
|
||||
用户登录
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Densen.Models.ids.AspNetUserLogins.AspNetUsers">
|
||||
<summary>
|
||||
用户
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.AspNetUserRoles">
|
||||
<summary>
|
||||
角色表
|
||||
<para>存储向哪些用户分配哪些角色</para>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.AspNetUsers">
|
||||
<summary>
|
||||
用户表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.AspNetUserTokens">
|
||||
<summary>
|
||||
用户令牌
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.DeviceCodes">
|
||||
<summary>
|
||||
设备代码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.Keys">
|
||||
<summary>
|
||||
密钥
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Densen.Models.ids.PersistedGrants">
|
||||
<summary>
|
||||
持久化保存
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Densen.Identity.Models.WebAppIdentityUser.Name">
|
||||
<summary>
|
||||
Full name
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Densen.Identity.Models.WebAppIdentityUser.DOB">
|
||||
<summary>
|
||||
Birth Date
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:UserGroup.GroupName">
|
||||
<summary>
|
||||
组名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:User1.Username">
|
||||
<summary>
|
||||
登陆名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:User1.Nickname">
|
||||
<summary>
|
||||
昵称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:User1.Avatar">
|
||||
<summary>
|
||||
头像
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:User1.Description">
|
||||
<summary>
|
||||
描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:base_entity.Program.TUserImg">
|
||||
<summary>
|
||||
用户图片2
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.Id">
|
||||
<summary>
|
||||
主键
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.EnterpriseId">
|
||||
<summary>
|
||||
企业
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.UserId">
|
||||
<summary>
|
||||
用户id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.Img">
|
||||
<summary>
|
||||
图片
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.CId">
|
||||
<summary>
|
||||
创建人Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.CName">
|
||||
<summary>
|
||||
创建人
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.CTime">
|
||||
<summary>
|
||||
创建日期
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.TUserImg.CTime2">
|
||||
<summary>
|
||||
创建日期2
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.Program.IDeleteSoft.IsDeleted">
|
||||
<summary>
|
||||
软删除
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.抖店实时销售金额表.ID">
|
||||
<summary>
|
||||
ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.抖店实时销售金额表.店铺名称">
|
||||
<summary>
|
||||
店铺名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.抖店实时销售金额表.日期">
|
||||
<summary>
|
||||
日期
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.抖店实时销售金额表.品牌名称">
|
||||
<summary>
|
||||
品牌名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.抖店实时销售金额表.成交金额">
|
||||
<summary>
|
||||
成交金额
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.抖店实时销售金额表.更新时间">
|
||||
<summary>
|
||||
更新时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.Id">
|
||||
<summary>
|
||||
主键标识
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.MchtAppId">
|
||||
<summary>
|
||||
商户应用Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.Describe">
|
||||
<summary>
|
||||
描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.Status">
|
||||
<summary>
|
||||
状态:0、关闭 1、启用
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.IsLimitUsePoints">
|
||||
<summary>
|
||||
是否限制使用积分:0、否 1、是
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.StartTime">
|
||||
<summary>
|
||||
开始时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.EndTime">
|
||||
<summary>
|
||||
结束时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.CreatedBy">
|
||||
<summary>
|
||||
创建人Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.CreatedTime">
|
||||
<summary>
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.UpdatedBy">
|
||||
<summary>
|
||||
最后编辑人Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.UpdatedTime">
|
||||
<summary>
|
||||
最后编辑时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.Deleted">
|
||||
<summary>
|
||||
是否删除:0、否 1、是
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.DeletedBy">
|
||||
<summary>
|
||||
删除人Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.MarketingRestrictions.DeletedTime">
|
||||
<summary>
|
||||
删除时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.RecordDate">
|
||||
<summary>
|
||||
创建日期
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.RecordHour">
|
||||
<summary>
|
||||
创建小时
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.RecordMinute">
|
||||
<summary>
|
||||
根据当前分钟数规整到10分钟的倍数
|
||||
例如 21分=>20分
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.RecordTime">
|
||||
<summary>
|
||||
记录时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.DeviceCode">
|
||||
<summary>
|
||||
设备Code
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.TerminalSequence">
|
||||
<summary>
|
||||
控制器序列号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.AvgValue">
|
||||
<summary>
|
||||
平均值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.RouteNum">
|
||||
<summary>
|
||||
路数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.CurrentDetail.PhaseTypeId">
|
||||
<summary>
|
||||
相类型
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.ProducerModel_Kafka.Sender">
|
||||
<summary>
|
||||
这个可以
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.ProducerModel_Kafka.ID">
|
||||
<summary>
|
||||
ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.ProducerModel_Kafka.IP">
|
||||
<summary>
|
||||
IP
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:base_entity.ProducerModel_Kafka.PConfig">
|
||||
<summary>
|
||||
这个不行
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ProjectItem.Code">
|
||||
<summary>
|
||||
编码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ProjectItem.MaxQuantity">
|
||||
<summary>
|
||||
实际最大用量
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ProjectItem.Name">
|
||||
<summary>
|
||||
名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:EMSServerModel.Model.Role">
|
||||
<summary>
|
||||
角色表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.Role.RoleId">
|
||||
<summary>
|
||||
角色编号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.Role.RoleName">
|
||||
<summary>
|
||||
角色名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.Role.RoleDesc">
|
||||
<summary>
|
||||
角色描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.Role.IsEnable">
|
||||
<summary>
|
||||
启用
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.Role.Users">
|
||||
<summary>
|
||||
角色用户多对多导航
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:EMSServerModel.Model.User">
|
||||
<summary>
|
||||
用户表bb123123
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.UserId">
|
||||
<summary>
|
||||
编号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Avatar">
|
||||
<summary>
|
||||
头像
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.UserName">
|
||||
<summary>
|
||||
姓名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.NickName">
|
||||
<summary>
|
||||
艺名
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Tel">
|
||||
<summary>
|
||||
电话
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Sex">
|
||||
<summary>
|
||||
性别
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.UID">
|
||||
<summary>
|
||||
证件号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.DateOfBirth">
|
||||
<summary>
|
||||
生日
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.PlaceOfBirth">
|
||||
<summary>
|
||||
出生地
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Addr">
|
||||
<summary>
|
||||
居住地
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Pwd">
|
||||
<summary>
|
||||
密码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.DeptId">
|
||||
<summary>
|
||||
部门编号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.TitleId">
|
||||
<summary>
|
||||
职务编号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Nationality">
|
||||
<summary>
|
||||
国籍
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Handler">
|
||||
<summary>
|
||||
经手人
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.IsEnable">
|
||||
<summary>
|
||||
启用
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Memos">
|
||||
<summary>
|
||||
备注
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.User.Roles">
|
||||
<summary>
|
||||
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:EMSServerModel.Model.Sex">
|
||||
<summary>
|
||||
性别枚举
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:EMSServerModel.Model.Sex.女">
|
||||
<summary>
|
||||
女=0
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:EMSServerModel.Model.Sex.男">
|
||||
<summary>
|
||||
男=1
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:EMSServerModel.Model.UserRole">
|
||||
<summary>
|
||||
用户角色关系表aa111
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.UserRole.RoleId">
|
||||
<summary>
|
||||
角色编号1
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.UserRole.Roles">
|
||||
<summary>
|
||||
角色导航
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.UserRole.UserId">
|
||||
<summary>
|
||||
用户编号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:EMSServerModel.Model.UserRole.Users">
|
||||
<summary>
|
||||
用户导航
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
25
Examples/base_entity/pgsql_test.cs
Normal file
25
Examples/base_entity/pgsql_test.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using NetTopologySuite.Geometries;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace base_entity
|
||||
{
|
||||
partial class Program
|
||||
{
|
||||
public static void test_pgsql(IFreeSql fsql)
|
||||
{
|
||||
var ddl = fsql.CodeFirst.GetComparisonDDLStatements<gistIndex>();
|
||||
}
|
||||
}
|
||||
|
||||
[Index("sidx_zjds_geom", nameof(Geom), IndexMethod = IndexMethod.GiST)]
|
||||
class gistIndex
|
||||
{
|
||||
public int bb { get; set; }
|
||||
public LineString Geom { get; set; }
|
||||
}
|
||||
}
|
130
Examples/base_entity/readme.md
Normal file
130
Examples/base_entity/readme.md
Normal file
@ -0,0 +1,130 @@
|
||||
# 前言
|
||||
|
||||
尝试过 ado.net、dapper、ef,以及Repository仓储,甚至自己还写过生成器工具,以便做常规CRUD操作。
|
||||
|
||||
它们日常操作不方便之处:
|
||||
|
||||
- 每次使用前需要声明,再操作;
|
||||
|
||||
- 很多人一个实体类,对应一个操作类(或DAL、DbContext、Repository);
|
||||
|
||||
BaseEntity 是一种极简单的 CodeFirst 开发方式,特别对单表或多表CRUD,利用继承节省了每个实体类的重复属性(创建时间、ID等字段),软件删除等功能,进行 crud 操作时不必时常考虑仓储的使用;
|
||||
|
||||
本文介绍 BaseEntity 一种极简约的 CRUD 操作方法。
|
||||
|
||||
# 功能特点
|
||||
|
||||
- 自动迁移实体结构(CodeFirst),到数据库;
|
||||
|
||||
- 直接操作实体的方法,进行 CRUD 操作;
|
||||
|
||||
- 简化用户定义实体类型,省去主键、常用字段的配置(如CreateTime、UpdateTime);
|
||||
|
||||
- 实现单表、多表查询的软删除逻辑;
|
||||
|
||||
# 声明
|
||||
|
||||
> dotnet add package FreeSql.Extensions.BaseEntity
|
||||
|
||||
> dotnet add package FreeSql.Provider.Sqlite
|
||||
|
||||
```csharp
|
||||
BaseEntity.Initialization(fsql, null);
|
||||
```
|
||||
|
||||
1、定义一个主键 int 并且自增的实体类型,BaseEntity TKey 指定为 int/long 时,会认为主键是自增;
|
||||
|
||||
```csharp
|
||||
public class UserGroup : BaseEntity<UserGroup, int>
|
||||
{
|
||||
public string GroupName { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
如果不想主键是自增键,可以重写属性:
|
||||
|
||||
```csharp
|
||||
public class UserGroup : BaseEntity<UserGroup, int>
|
||||
{
|
||||
[Column(IsIdentity = false)]
|
||||
public override int Id { 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
|
||||
|
||||
2、定义一个主键 Guid 的实体类型,保存数据时会自动产生有序不重复的 Guid 值(不用自己指定 Guid.NewGuid());
|
||||
|
||||
```csharp
|
||||
public class User : BaseEntity<UserGroup, Guid>
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
# CRUD 使用
|
||||
|
||||
```csharp
|
||||
//添加
|
||||
var item = new UserGroup { GroupName = "组一" };
|
||||
item.Insert();
|
||||
|
||||
//更新
|
||||
item.GroupName = "组二";
|
||||
item.Update();
|
||||
|
||||
//添加或更新
|
||||
item.Save();
|
||||
|
||||
//软删除
|
||||
item.Delete();
|
||||
|
||||
//恢复软删除
|
||||
item.Restore();
|
||||
|
||||
//根据主键获取对象
|
||||
var item = UserGroup.Find(1);
|
||||
|
||||
//查询数据
|
||||
var items = UserGroup.Where(a => a.Id > 10).ToList();
|
||||
```
|
||||
|
||||
实体类型.Select 是一个查询对象,使用方法和 FreeSql.ISelect 一样;
|
||||
|
||||
支持多表查询时,软删除条件会附加在每个表中;
|
||||
|
||||
> 有关更多查询方法,请参考资料:https://github.com/2881099/FreeSql/wiki/%e6%9f%a5%e8%af%a2
|
||||
|
||||
# 事务建议
|
||||
|
||||
由于 AsyncLocal 平台兼容不好,所以交给外部管理事务。
|
||||
|
||||
```csharp
|
||||
static AsyncLocal<IUnitOfWork> _asyncUow = new AsyncLocal<IUnitOfWork>();
|
||||
|
||||
BaseEntity.Initialization(fsql, () => _asyncUow.Value);
|
||||
```
|
||||
|
||||
在 Scoped 开始时: _asyncUow.Value = fsql.CreateUnitOfWork(); (也可以使用 UnitOfWorkManager 对象获取 uow)
|
||||
|
||||
在 Scoped 结束时:_asyncUow.Value = null;
|
||||
|
||||
如下:
|
||||
|
||||
```csharp
|
||||
using (var uow = fsql.CreateUnitOfWork())
|
||||
{
|
||||
_asyncUow.Value = uow;
|
||||
|
||||
try
|
||||
{
|
||||
//todo ... BaseEntity 内部 curd 方法保持使用 uow 事务
|
||||
}
|
||||
finally
|
||||
{
|
||||
_asyncUow.Value = null;
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
}
|
||||
```
|
291
Examples/benchmarker/Program.cs
Normal file
291
Examples/benchmarker/Program.cs
Normal file
@ -0,0 +1,291 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SqlSugar;
|
||||
|
||||
namespace FreeSql.Bechmarker
|
||||
{
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
//var summaryInsert = BenchmarkRunner.Run<OrmVsInsert>();
|
||||
var summarySelect = BenchmarkRunner.Run<OrmVsSelect>(new BenchmarkDotNet.Configs.DebugBuildConfig
|
||||
{
|
||||
|
||||
});
|
||||
//var summaryUpdate = BenchmarkRunner.Run<OrmVsUpdate>();
|
||||
|
||||
Console.ReadKey();
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
public class Orm
|
||||
{
|
||||
public static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer,
|
||||
"Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=103;TrustServerCertificate=true;Encrypt=False",
|
||||
typeof(FreeSql.SqlServer.SqlServerProvider<>))
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=20")
|
||||
.UseAutoSyncStructure(false)
|
||||
.UseNoneCommandParameter(true)
|
||||
//.UseConfigEntityFromDbFirst(true)
|
||||
.Build();
|
||||
|
||||
public static SqlSugarClient sugar
|
||||
{
|
||||
get => new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=102;TrustServerCertificate=true;Encrypt=False",
|
||||
DbType = DbType.SqlServer,
|
||||
//ConnectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=20;Max Pool Size=20",
|
||||
//DbType = DbType.MySql,
|
||||
IsAutoCloseConnection = true,
|
||||
InitKeyType = InitKeyType.Attribute
|
||||
});
|
||||
}
|
||||
}
|
||||
class SongContext : DbContext
|
||||
{
|
||||
public DbSet<Song> Songs { get; set; }
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
optionsBuilder.UseSqlServer("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=101;TrustServerCertificate=true;Encrypt=False");
|
||||
//optionsBuilder.UseMySql("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=21;Max Pool Size=21");
|
||||
}
|
||||
}
|
||||
|
||||
[RPlotExporter, RankColumn]
|
||||
public class OrmVsInsert
|
||||
{
|
||||
public IEnumerable<Song> songs;
|
||||
|
||||
[Params(1, 500)]
|
||||
public int size;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "freesql_song");
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "sugar_song");
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "efcore_song");
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "dapper_song");
|
||||
|
||||
//测试前清空数据
|
||||
Orm.fsql.Delete<Song>().Where(a => a.Id > 0).ExecuteAffrows();
|
||||
Orm.sugar.Deleteable<Song>().Where(a => a.Id > 0).ExecuteCommand();
|
||||
Orm.fsql.Ado.ExecuteNonQuery("delete from efcore_song");
|
||||
|
||||
songs = Enumerable.Range(0, size).Select(a => new Song
|
||||
{
|
||||
Create_time = DateTime.Now,
|
||||
Is_deleted = false,
|
||||
Title = $"Insert_{a}",
|
||||
Url = $"Url_{a}"
|
||||
});
|
||||
|
||||
//预热
|
||||
Orm.fsql.Insert(songs.First()).ExecuteAffrows();
|
||||
Orm.sugar.Insertable(songs.First()).ExecuteCommand();
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
db.Songs.AddRange(songs.First());
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int FreeSqlInsert() => Orm.fsql.Insert(songs).ExecuteAffrows();
|
||||
|
||||
[Benchmark]
|
||||
public int SqlSugarInsert() => Orm.sugar.Insertable(songs.ToArray()).ExecuteCommand();
|
||||
|
||||
[Benchmark]
|
||||
public int EfCoreInsert()
|
||||
{
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
db.Songs.AddRange(songs.ToArray());
|
||||
return db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int DapperInsert()
|
||||
{
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=100;TrustServerCertificate=true;Encrypt=False"))
|
||||
{
|
||||
foreach (var song in songs)
|
||||
{
|
||||
Dapper.SqlMapper.Execute(conn, @$"insert into dapper_song(Create_time,Is_deleted,Title,Url)
|
||||
values('{song.Create_time.Value.ToString("yyyy-MM-dd HH:mm:ss")}',{(song.Is_deleted == true ? 1 : 0)},'{song.Title}','{song.Url}')");
|
||||
}
|
||||
}
|
||||
return songs.Count();
|
||||
}
|
||||
}
|
||||
|
||||
[RPlotExporter, RankColumn]
|
||||
public class OrmVsUpdate
|
||||
{
|
||||
public List<Song> songs;
|
||||
|
||||
[Params(1, 500)]
|
||||
public int size;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
songs = Orm.fsql.Select<Song>().Limit(size).ToList();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int FreeSqlUpdate() => Orm.fsql.Update<Song>().SetSource(songs).ExecuteAffrows();
|
||||
|
||||
[Benchmark]
|
||||
public int SqlSugarUpdate() => Orm.sugar.Updateable(songs).ExecuteCommand();
|
||||
|
||||
[Benchmark]
|
||||
public int EfCoreUpdate()
|
||||
{
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
db.Songs.UpdateRange(songs.ToArray());
|
||||
return db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int DapperUpdate()
|
||||
{
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=100;TrustServerCertificate=true;Encrypt=False"))
|
||||
{
|
||||
foreach (var song in songs)
|
||||
{
|
||||
Dapper.SqlMapper.Execute(conn, @$"update dapper_song set
|
||||
Create_time = '{song.Create_time.Value.ToString("yyyy-MM-dd HH:mm:ss")}',
|
||||
Is_deleted = {(song.Is_deleted == true ? 1 : 0)},
|
||||
Title = '{song.Title}',
|
||||
Url = '{song.Url}'
|
||||
where id = {song.Id}");
|
||||
}
|
||||
}
|
||||
return songs.Count();
|
||||
}
|
||||
}
|
||||
|
||||
[RPlotExporter, RankColumn]
|
||||
public class OrmVsSelect
|
||||
{
|
||||
|
||||
[Params(1, 500)]
|
||||
public int size;
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup2()
|
||||
{
|
||||
Orm.fsql.Select<Song>().Limit(1).ToList();
|
||||
Orm.sugar.Queryable<Song>().Take(1).ToList();
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
db.Songs.Take(1).AsNoTracking().ToList();
|
||||
}
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=100;TrustServerCertificate=true;Encrypt=False"))
|
||||
{
|
||||
Dapper.SqlMapper.Query<Song>(conn, $"select top {1} Id,Create_time,Is_deleted,Title,Url from dapper_song").ToList();
|
||||
}
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "freesql_song");
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "sugar_song");
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "efcore_song");
|
||||
Orm.fsql.CodeFirst.SyncStructure(typeof(Song), "dapper_song");
|
||||
|
||||
//测试前清空数据
|
||||
Orm.fsql.Delete<Song>().Where(a => a.Id > 0).ExecuteAffrows();
|
||||
Orm.sugar.Deleteable<Song>().Where(a => a.Id > 0).ExecuteCommand();
|
||||
Orm.fsql.Ado.ExecuteNonQuery("delete from efcore_song");
|
||||
Orm.fsql.Ado.ExecuteNonQuery("delete from dapper_song");
|
||||
|
||||
var songs = Enumerable.Range(0, size).Select(a => new Song
|
||||
{
|
||||
Create_time = DateTime.Now,
|
||||
Is_deleted = false,
|
||||
Title = $"Insert_{a}",
|
||||
Url = $"Url_{a}"
|
||||
});
|
||||
|
||||
//预热
|
||||
Orm.fsql.Insert(songs).ExecuteAffrows();
|
||||
Orm.sugar.Insertable(songs.ToArray()).ExecuteCommand();
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
db.Songs.AddRange(songs);
|
||||
db.SaveChanges();
|
||||
}
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=100;TrustServerCertificate=true;Encrypt=False"))
|
||||
{
|
||||
foreach (var song in songs)
|
||||
{
|
||||
Dapper.SqlMapper.Execute(conn, @$"insert into dapper_song(Create_time,Is_deleted,Title,Url)
|
||||
values('{song.Create_time.Value.ToString("yyyy-MM-dd HH:mm:ss")}',{(song.Is_deleted == true ? 1 : 0)},'{song.Title}','{song.Url}')");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public List<Song> FreeSqlSelect() => Orm.fsql.Select<Song>().Limit(size).ToList();
|
||||
|
||||
[Benchmark]
|
||||
public List<Song> SqlSugarSelect() => Orm.sugar.Queryable<Song>().Take(size).ToList();
|
||||
|
||||
[Benchmark]
|
||||
public List<Song> EfCoreSelect()
|
||||
{
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
return db.Songs.Take(size).AsNoTracking().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public List<Song> DapperSelete()
|
||||
{
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=100;TrustServerCertificate=true;Encrypt=False"))
|
||||
{
|
||||
return Dapper.SqlMapper.Query<Song>(conn, $"select top {size} Id,Create_time,Is_deleted,Title,Url from dapper_song").ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_song")]
|
||||
[SugarTable("sugar_song")]
|
||||
[Table("efcore_song")]
|
||||
public class Song
|
||||
{
|
||||
[FreeSql.DataAnnotations.Column(IsIdentity = true)]
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
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; }
|
||||
}
|
||||
}
|
20
Examples/benchmarker/benchmarker.csproj
Normal file
20
Examples/benchmarker/benchmarker.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
|
||||
<PackageReference Include="sqlSugarCore" Version="5.1.3.38" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServerForSystem\FreeSql.Provider.SqlServerForSystem.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
12
Examples/dbcontext_01/.config/dotnet-tools.json
Normal file
12
Examples/dbcontext_01/.config/dotnet-tools.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "5.0.0",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
251
Examples/dbcontext_01/Controllers/ValuesController.cs
Normal file
251
Examples/dbcontext_01/Controllers/ValuesController.cs
Normal file
@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using FreeSql;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace dbcontext_01.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
|
||||
private readonly IFreeSql _orm;
|
||||
private readonly SongContext _songContext;
|
||||
private readonly CurdAfterLog _curdLog;
|
||||
public ValuesController(SongContext songContext, IFreeSql orm1, CurdAfterLog curdLog)
|
||||
{
|
||||
_songContext = songContext;
|
||||
_orm = orm1;
|
||||
_curdLog = curdLog;
|
||||
|
||||
}
|
||||
|
||||
// GET api/values
|
||||
[HttpGet]
|
||||
public async Task<string> Get()
|
||||
{
|
||||
_orm.SetDbContextOptions(opt =>
|
||||
{
|
||||
opt.OnEntityChange = changeReport =>
|
||||
{
|
||||
Console.WriteLine(changeReport);
|
||||
};
|
||||
});
|
||||
|
||||
long id = 0;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var repos2Song = _orm.GetRepository<Song, int>();
|
||||
repos2Song.Where(a => a.Id > 10).ToList();
|
||||
//查询结果,进入 states
|
||||
|
||||
var song = new Song { Title = "empty" };
|
||||
repos2Song.Insert(song);
|
||||
song.Title = "empty01";
|
||||
repos2Song.Update(song);
|
||||
id = song.Id;
|
||||
|
||||
var adds = Enumerable.Range(0, 100)
|
||||
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
|
||||
.ToList();
|
||||
//创建一堆无主键值
|
||||
|
||||
repos2Song.Insert(adds);
|
||||
|
||||
for (var a = 0; a < 10; a++)
|
||||
adds[a].Title = "dkdkdkdk" + a;
|
||||
|
||||
repos2Song.Update(adds);
|
||||
//批量修改
|
||||
|
||||
repos2Song.Delete(adds.Skip(10).Take(20).ToList());
|
||||
//批量删除,10-20 元素的主键值会被清除
|
||||
|
||||
adds.Last().Url = "skldfjlksdjglkjjcccc";
|
||||
repos2Song.Update(adds.Last());
|
||||
|
||||
adds.First().Url = "skldfjlksdjglkjjcccc";
|
||||
repos2Song.Update(adds.First());
|
||||
|
||||
|
||||
var ctx = _songContext;
|
||||
var tag = new Tag
|
||||
{
|
||||
Name = "testaddsublist"
|
||||
};
|
||||
ctx.Tags.Add(tag);
|
||||
|
||||
|
||||
ctx.UnitOfWork.GetOrBeginTransaction();
|
||||
|
||||
var tagAsync = new Tag
|
||||
{
|
||||
Name = "testaddsublist"
|
||||
};
|
||||
await ctx.Tags.AddAsync(tagAsync);
|
||||
|
||||
|
||||
ctx.Songs.Select.Where(a => a.Id > 10).ToList();
|
||||
//查询结果,进入 states
|
||||
|
||||
song = new Song { Title = "empty" };
|
||||
//可插入的 song
|
||||
|
||||
ctx.Songs.Add(song);
|
||||
id = song.Id;
|
||||
//因有自增类型,立即开启事务执行SQL,返回自增值
|
||||
|
||||
adds = Enumerable.Range(0, 100)
|
||||
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
|
||||
.ToList();
|
||||
//创建一堆无主键值
|
||||
|
||||
ctx.Songs.AddRange(adds);
|
||||
//立即执行,将自增值赋给 adds 所有元素,因为有自增类型,如果其他类型,指定传入主键值,不会立即执行
|
||||
|
||||
for (var a = 0; a < 10; a++)
|
||||
adds[a].Title = "dkdkdkdk" + a;
|
||||
|
||||
ctx.Songs.UpdateRange(adds);
|
||||
//批量修改,进入队列
|
||||
|
||||
ctx.Songs.RemoveRange(adds.Skip(10).Take(20).ToList());
|
||||
//批量删除,进入队列,完成时 10-20 元素的主键值会被清除
|
||||
|
||||
//ctx.Songs.Update(adds.First());
|
||||
|
||||
adds.Last().Url = "skldfjlksdjglkjjcccc";
|
||||
ctx.Songs.Update(adds.Last());
|
||||
|
||||
adds.First().Url = "skldfjlksdjglkjjcccc";
|
||||
ctx.Songs.Update(adds.First());
|
||||
|
||||
//单条修改 urls 的值,进入队列
|
||||
|
||||
//throw new Exception("回滚");
|
||||
|
||||
//ctx.Songs.Select.First();
|
||||
//这里做一个查询,会立即打包【执行队列】,避免没有提交的数据,影响查询结果
|
||||
|
||||
ctx.SaveChanges();
|
||||
//打包【执行队列】,提交事务
|
||||
|
||||
|
||||
using (var uow = _orm.CreateUnitOfWork())
|
||||
{
|
||||
|
||||
var reposSong = uow.GetRepository<Song, int>();
|
||||
reposSong.Where(a => a.Id > 10).ToList();
|
||||
//查询结果,进入 states
|
||||
|
||||
song = new Song { Title = "empty" };
|
||||
reposSong.Insert(song);
|
||||
id = song.Id;
|
||||
|
||||
adds = Enumerable.Range(0, 100)
|
||||
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
|
||||
.ToList();
|
||||
//创建一堆无主键值
|
||||
|
||||
reposSong.Insert(adds);
|
||||
|
||||
for (var a = 0; a < 10; a++)
|
||||
adds[a].Title = "dkdkdkdk" + a;
|
||||
|
||||
reposSong.Update(adds);
|
||||
//批量修改
|
||||
|
||||
reposSong.Delete(adds.Skip(10).Take(20).ToList());
|
||||
//批量删除,10-20 元素的主键值会被清除
|
||||
|
||||
adds.Last().Url = "skldfjlksdjglkjjcccc";
|
||||
reposSong.Update(adds.Last());
|
||||
|
||||
adds.First().Url = "skldfjlksdjglkjjcccc";
|
||||
reposSong.Update(adds.First());
|
||||
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
using (ctx = new SongContext())
|
||||
{
|
||||
|
||||
song = new Song { Title = "empty" };
|
||||
await ctx.Songs.AddAsync(song);
|
||||
id = song.Id;
|
||||
|
||||
adds = Enumerable.Range(0, 100)
|
||||
.Select(a => new Song { CreateTime = DateTime.Now, Title = "xxxx" + a, Url = "url222" })
|
||||
.ToList();
|
||||
await ctx.Songs.AddRangeAsync(adds);
|
||||
|
||||
for (var a = 0; a < adds.Count; a++)
|
||||
adds[a].Title = "dkdkdkdk" + a;
|
||||
|
||||
ctx.Songs.UpdateRange(adds);
|
||||
|
||||
ctx.Songs.RemoveRange(adds.Skip(10).Take(20).ToList());
|
||||
|
||||
//ctx.Songs.Update(adds.First());
|
||||
|
||||
adds.Last().Url = "skldfjlksdjglkjjcccc";
|
||||
ctx.Songs.Update(adds.Last());
|
||||
|
||||
//throw new Exception("回滚");
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
var item = await _orm.Select<Song>().Where(a => a.Id == id).FirstAsync();
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
var item22 = await _orm.Select<Song>().Where(a => a.Id == id).FirstAsync();
|
||||
var item33 = await _orm.Select<Song>().Where(a => a.Id > id).ToListAsync();
|
||||
|
||||
return item22.Id.ToString() + "\r\n\r\n" + _curdLog.Sb.ToString();
|
||||
}
|
||||
|
||||
// GET api/values/5
|
||||
[HttpGet("{id}")]
|
||||
public ActionResult<object> Get(int id)
|
||||
{
|
||||
return _orm.Select<Song>().Where(a => a.Id == id).First();
|
||||
}
|
||||
|
||||
[HttpGet("get{id}")]
|
||||
public ActionResult<string> Get2(int id)
|
||||
{
|
||||
var item1 = _orm.Select<Song>().Where(a => a.Id == id).First();
|
||||
var item2 = _orm.Select<Song>().Where(a => a.Id == id).First();
|
||||
return _curdLog.Sb.ToString();
|
||||
}
|
||||
|
||||
// POST api/values
|
||||
[HttpPost]
|
||||
public void Post([FromBody] string value)
|
||||
{
|
||||
}
|
||||
|
||||
// PUT api/values/5
|
||||
[HttpPut("{id}")]
|
||||
public void Put(int id, [FromBody] string value)
|
||||
{
|
||||
}
|
||||
|
||||
// DELETE api/values/5
|
||||
[HttpDelete("{id}")]
|
||||
public void Delete(int id)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
113
Examples/dbcontext_01/DbContexts/SongContext.cs
Normal file
113
Examples/dbcontext_01/DbContexts/SongContext.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace dbcontext_01
|
||||
{
|
||||
public class SongContext : DbContext
|
||||
{
|
||||
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 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; }
|
||||
}
|
||||
}
|
28
Examples/dbcontext_01/Program.cs
Normal file
28
Examples/dbcontext_01/Program.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace dbcontext_01
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<DeleteExistingFiles>True</DeleteExistingFiles>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<PublishProvider>FileSystem</PublishProvider>
|
||||
<PublishUrl>bin\Release\net5.0\publish\</PublishUrl>
|
||||
<WebPublishMethod>FileSystem</WebPublishMethod>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||
<ProjectGuid>690f89e0-a721-423f-8f5d-d262f73235ea</ProjectGuid>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>True</PublishSingleFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
27
Examples/dbcontext_01/Properties/launchSettings.json
Normal file
27
Examples/dbcontext_01/Properties/launchSettings.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:53030/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"dbcontext_01": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:53031/"
|
||||
}
|
||||
}
|
||||
}
|
84
Examples/dbcontext_01/Startup.cs
Normal file
84
Examples/dbcontext_01/Startup.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using FreeSql;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace dbcontext_01
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
|
||||
{
|
||||
Configuration = configuration;
|
||||
|
||||
Fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document2.db;Pooling=true;Max Pool Size=10")
|
||||
//.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=10")
|
||||
//.UseConnectionString(DataType.MySql, "Data Source=192.168.164.10;Port=33061;User ID=root;Password=123456;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=5")
|
||||
//.UseSlave("Data Source=192.168.164.10;Port=33062;User ID=root;Password=123456;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=5")
|
||||
//.UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=10")
|
||||
//.UseSyncStructureToUpper(true)
|
||||
.UseAutoSyncStructure(true)
|
||||
.UseLazyLoading(true)
|
||||
.UseNoneCommandParameter(true)
|
||||
.UseMonitorCommand(cmd => { }, (cmd, log) => Trace.WriteLine(log))
|
||||
.Build();
|
||||
|
||||
Fsql.Aop.CurdAfter += (s, e) =>
|
||||
{
|
||||
Console.WriteLine(e.Identifier + ": " + e.EntityType.FullName + " " + e.ElapsedMilliseconds + "ms, " + e.Sql);
|
||||
CurdAfterLog.Current.Value?.Sb.AppendLine($"{Thread.CurrentThread.ManagedThreadId}: {e.EntityType.FullName} {e.ElapsedMilliseconds}ms, {e.Sql}");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
enum MySql { }
|
||||
enum PgSql { }
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public static IFreeSql Fsql { get; private set; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllersWithViews();
|
||||
|
||||
services.AddSingleton<IFreeSql>(Fsql);
|
||||
services.AddFreeDbContext<SongContext>(options => options.UseFreeSql(Fsql));
|
||||
services.AddScoped<CurdAfterLog>();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
Console.OutputEncoding = Encoding.GetEncoding("GB2312");
|
||||
Console.InputEncoding = Encoding.GetEncoding("GB2312");
|
||||
|
||||
app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(a => a.MapControllers());
|
||||
}
|
||||
}
|
||||
|
||||
public class CurdAfterLog : IDisposable
|
||||
{
|
||||
public static AsyncLocal<CurdAfterLog> Current = new AsyncLocal<CurdAfterLog>();
|
||||
public StringBuilder Sb { get; } = new StringBuilder();
|
||||
|
||||
public CurdAfterLog()
|
||||
{
|
||||
Current.Value = this;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Sb.Clear();
|
||||
Current.Value = null;
|
||||
}
|
||||
}
|
||||
}
|
9
Examples/dbcontext_01/appsettings.Development.json
Normal file
9
Examples/dbcontext_01/appsettings.Development.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
8
Examples/dbcontext_01/appsettings.json
Normal file
8
Examples/dbcontext_01/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
25
Examples/dbcontext_01/dbcontext_01.csproj
Normal file
25
Examples/dbcontext_01/dbcontext_01.csproj
Normal file
@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>dbcontext_01.xml</DocumentationFile>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<NoWarn>1701;1702;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" />
|
||||
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
8
Examples/dbcontext_01/dbcontext_01.xml
Normal file
8
Examples/dbcontext_01/dbcontext_01.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>dbcontext_01</name>
|
||||
</assembly>
|
||||
<members>
|
||||
</members>
|
||||
</doc>
|
33
Examples/efcore_to_freesql/DBContexts/BaseDBContext.cs
Normal file
33
Examples/efcore_to_freesql/DBContexts/BaseDBContext.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using efcore_to_freesql.Entitys;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
|
||||
namespace efcore_to_freesql.DBContexts
|
||||
{
|
||||
|
||||
public class BaseDBContext : DbContext
|
||||
{
|
||||
|
||||
public static IFreeSql Fsql { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
Fsql.CodeFirst.ConfigEntity(modelBuilder.Model); //ͬ<><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
//<2F><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>
|
||||
Fsql.CodeFirst.ApplyConfiguration(new SongConfiguration());
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//Fsql.CodeFirst.ApplyConfigurationsFromAssembly(typeof(SongConfiguration).Assembly);
|
||||
|
||||
Fsql.CodeFirst.SyncStructure<Song>();
|
||||
|
||||
}
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
optionsBuilder.UseSqlite(@"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10");
|
||||
}
|
||||
}
|
||||
}
|
21
Examples/efcore_to_freesql/DBContexts/Topic1Context.cs
Normal file
21
Examples/efcore_to_freesql/DBContexts/Topic1Context.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using efcore_to_freesql.Entitys;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace efcore_to_freesql.DBContexts
|
||||
{
|
||||
|
||||
public class Topic1Context : BaseDBContext
|
||||
{
|
||||
|
||||
public DbSet<Topic1> Topic1s { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
|
||||
modelBuilder.Entity<Topic1>().ToTable("topic1_sss").HasKey(a => a.Id);
|
||||
modelBuilder.Entity<Topic1>().Property(a => a.Id).HasColumnName("topic1_id").ValueGeneratedOnAdd();
|
||||
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
}
|
21
Examples/efcore_to_freesql/DBContexts/Topic2Context.cs
Normal file
21
Examples/efcore_to_freesql/DBContexts/Topic2Context.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using efcore_to_freesql.Entitys;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace efcore_to_freesql.DBContexts
|
||||
{
|
||||
|
||||
public class Topic2Context : BaseDBContext
|
||||
{
|
||||
|
||||
public DbSet<Topic2> Topic2s { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
|
||||
modelBuilder.Entity<Topic2>().ToTable("topic2_sss");
|
||||
modelBuilder.Entity<Topic2>().Property(a => a.Id).HasColumnName("topic2_id");
|
||||
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
}
|
48
Examples/efcore_to_freesql/Entitys/Song.cs
Normal file
48
Examples/efcore_to_freesql/Entitys/Song.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace efcore_to_freesql.Entitys
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
14
Examples/efcore_to_freesql/Entitys/Topic1.cs
Normal file
14
Examples/efcore_to_freesql/Entitys/Topic1.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace efcore_to_freesql.Entitys
|
||||
{
|
||||
|
||||
public class Topic1
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
}
|
18
Examples/efcore_to_freesql/Entitys/Topic2.cs
Normal file
18
Examples/efcore_to_freesql/Entitys/Topic2.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace efcore_to_freesql.Entitys
|
||||
{
|
||||
|
||||
public class Topic2
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
using efcore_to_freesql.Entitys;
|
||||
using FreeSql;
|
||||
using FreeSql.Extensions.EfCoreFluentApi;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public static class CodeFirstExtensions
|
||||
{
|
||||
|
||||
public static void ConfigEntity(this ICodeFirst codeFirst, IMutableModel efmodel)
|
||||
{
|
||||
|
||||
foreach (var type in efmodel.GetEntityTypes())
|
||||
{
|
||||
|
||||
codeFirst.ConfigEntity(type.ClrType, a =>
|
||||
{
|
||||
|
||||
//表名
|
||||
var relationalTableName = type.FindAnnotation("Relational:TableName");
|
||||
if (relationalTableName != null)
|
||||
a.Name(relationalTableName.Value?.ToString() ?? type.ClrType.Name);
|
||||
|
||||
foreach (var prop in type.GetProperties())
|
||||
{
|
||||
|
||||
var freeProp = a.Property(prop.Name);
|
||||
|
||||
//列名
|
||||
var relationalColumnName = prop.FindAnnotation("Relational:ColumnName");
|
||||
if (relationalColumnName != null)
|
||||
freeProp.Name(relationalColumnName.Value?.ToString() ?? prop.Name);
|
||||
|
||||
//主键
|
||||
freeProp.IsPrimary(prop.IsPrimaryKey());
|
||||
|
||||
//自增
|
||||
freeProp.IsIdentity(
|
||||
prop.ValueGenerated == ValueGenerated.Never ||
|
||||
prop.ValueGenerated == ValueGenerated.OnAdd ||
|
||||
prop.GetAnnotations().Where(z =>
|
||||
z.Name == "SqlServer:ValueGenerationStrategy" && z.Value.ToString().Contains("IdentityColumn") //sqlserver 自增
|
||||
|| z.Value.ToString().Contains("IdentityColumn") //其他数据库实现未经测试
|
||||
).Any()
|
||||
);
|
||||
|
||||
//可空
|
||||
freeProp.IsNullable(prop.GetAfterSaveBehavior() != PropertySaveBehavior.Throw);
|
||||
|
||||
//类型
|
||||
var relationalColumnType = prop.FindAnnotation("Relational:ColumnType");
|
||||
if (relationalColumnType != null)
|
||||
{
|
||||
|
||||
var dbType = relationalColumnType.ToString();
|
||||
if (!string.IsNullOrEmpty(dbType))
|
||||
{
|
||||
|
||||
var maxLength = prop.FindAnnotation("MaxLength");
|
||||
if (maxLength != null)
|
||||
dbType += $"({maxLength})";
|
||||
|
||||
freeProp.DbType(dbType);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void EfCoreFluentApiTestGeneric(this ICodeFirst cf)
|
||||
{
|
||||
cf.Entity<Song>(eb =>
|
||||
{
|
||||
eb.ToTable("tb_song1");
|
||||
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_tb_song1111");
|
||||
|
||||
//一对多、多对一
|
||||
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.ToTable("tb_songtype1");
|
||||
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 static void EfCoreFluentApiTestDynamic(this ICodeFirst cf)
|
||||
{
|
||||
cf.Entity(typeof(Song), eb =>
|
||||
{
|
||||
eb.ToTable("tb_song2");
|
||||
eb.Ignore("Field1");
|
||||
eb.Property("Title").HasColumnType("varchar(50)").IsRequired();
|
||||
eb.Property("Url").HasMaxLength(100);
|
||||
|
||||
eb.Property("RowVersion").IsRowVersion();
|
||||
eb.Property("CreateTime").HasDefaultValueSql("current_timestamp");
|
||||
|
||||
eb.HasKey("Id");
|
||||
eb.HasIndex("Title").IsUnique().HasName("idx_tb_song2222");
|
||||
|
||||
//一对多、多对一
|
||||
eb.HasOne("Type").HasForeignKey("TypeId").WithMany("Songs");
|
||||
|
||||
//多对多
|
||||
eb.HasMany("Tags").WithMany("Songs", typeof(Song_tag));
|
||||
});
|
||||
cf.Entity(typeof(SongType), eb =>
|
||||
{
|
||||
eb.ToTable("tb_songtype2");
|
||||
eb.HasMany("Songs").WithOne("Type").HasForeignKey("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 SongConfiguration : FreeSql.Extensions.EfCoreFluentApi.IEntityTypeConfiguration<Song>
|
||||
{
|
||||
public void Configure(EfCoreTableFluent<Song> eb)
|
||||
{
|
||||
eb.ToTable("tb_song_config");
|
||||
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_tb_song1111");
|
||||
|
||||
//一对多、多对一
|
||||
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));
|
||||
}
|
||||
}
|
24
Examples/efcore_to_freesql/Program.cs
Normal file
24
Examples/efcore_to_freesql/Program.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace efcore_to_freesql
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
30
Examples/efcore_to_freesql/Properties/launchSettings.json
Normal file
30
Examples/efcore_to_freesql/Properties/launchSettings.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:58143",
|
||||
"sslPort": 44349
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"efcore_to_freesql": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
87
Examples/efcore_to_freesql/Startup.cs
Normal file
87
Examples/efcore_to_freesql/Startup.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using efcore_to_freesql.DBContexts;
|
||||
using efcore_to_freesql.Entitys;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace efcore_to_freesql
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
|
||||
{
|
||||
Configuration = configuration;
|
||||
|
||||
Fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10")
|
||||
.UseAutoSyncStructure(true)
|
||||
.Build();
|
||||
|
||||
//Fsql.CodeFirst.EfCoreFluentApiTestGeneric();
|
||||
//Fsql.CodeFirst.EfCoreFluentApiTestDynamic();
|
||||
|
||||
BaseDBContext.Fsql = Fsql;
|
||||
|
||||
var sql11 = Fsql.Select<Topic1>().ToSql();
|
||||
//SELECT a."Id", a."Title", a."CreateTime" FROM "Topic1" a
|
||||
var sql12 = Fsql.Insert<Topic1>().AppendData(new Topic1()).ToSql();
|
||||
//INSERT INTO "Topic1"("Id", "Title", "CreateTime") VALUES(@Id0, @Title0, @CreateTime0)
|
||||
|
||||
var sql21 = Fsql.Select<Topic2>().ToSql();
|
||||
//SELECT a."Id", a."Title", a."CreateTime" FROM "Topic2" a
|
||||
var sql22 = Fsql.Insert<Topic2>().AppendData(new Topic2()).ToSql();
|
||||
//INSERT INTO "Topic2"("Id", "Title", "CreateTime") VALUES(@Id0, @Title0, @CreateTime0)
|
||||
|
||||
using (var db = new Topic1Context())
|
||||
{
|
||||
db.Topic1s.Add(new Topic1());
|
||||
}
|
||||
using (var db = new Topic2Context())
|
||||
{
|
||||
db.Topic2s.Add(new Topic2());
|
||||
}
|
||||
|
||||
var sql13 = Fsql.Select<Topic1>().ToSql();
|
||||
//SELECT a."topic1_id", a."Title", a."CreateTime" FROM "topic1_sss" a
|
||||
var sql14 = Fsql.Insert<Topic1>().AppendData(new Topic1()).ToSql();
|
||||
//INSERT INTO "topic1_sss"("Title", "CreateTime") VALUES(@Title0, @CreateTime0)
|
||||
|
||||
var sql23 = Fsql.Select<Topic2>().ToSql();
|
||||
//SELECT a."topic2_id", a."Title", a."CreateTime" FROM "topic2_sss" a
|
||||
var sql24 = Fsql.Insert<Topic2>().AppendData(new Topic2()).ToSql();
|
||||
//INSERT INTO "topic2_sss"("Title", "CreateTime") VALUES(@Title0, @CreateTime0)
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IFreeSql Fsql { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllersWithViews();
|
||||
services.AddSingleton<IFreeSql>(Fsql);
|
||||
services.AddMvc();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
Console.OutputEncoding = Encoding.GetEncoding("GB2312");
|
||||
Console.InputEncoding = Encoding.GetEncoding("GB2312");
|
||||
|
||||
app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(a => a.MapControllers());
|
||||
}
|
||||
}
|
||||
}
|
9
Examples/efcore_to_freesql/appsettings.Development.json
Normal file
9
Examples/efcore_to_freesql/appsettings.Development.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
8
Examples/efcore_to_freesql/appsettings.json
Normal file
8
Examples/efcore_to_freesql/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
18
Examples/efcore_to_freesql/efcore_to_freesql.csproj
Normal file
18
Examples/efcore_to_freesql/efcore_to_freesql.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
|
||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
814
Examples/orm_vs/Program.cs
Normal file
814
Examples/orm_vs/Program.cs
Normal file
@ -0,0 +1,814 @@
|
||||
using Dapper;
|
||||
using FreeSql.Internal;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FreeSql;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
|
||||
namespace orm_vs
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Max Pool Size=21;TrustServerCertificate=true")
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=21;AllowLoadLocalInfile=true;")
|
||||
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=127.0.0.1;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=21")
|
||||
.UseAutoSyncStructure(false)
|
||||
.UseNoneCommandParameter(true)
|
||||
//.UseConfigEntityFromDbFirst(true)
|
||||
.Build();
|
||||
|
||||
static SqlSugarClient sugar
|
||||
{
|
||||
get
|
||||
{
|
||||
var db = new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=20;Max Pool Size=20;TrustServerCertificate=true",
|
||||
DbType = DbType.SqlServer,
|
||||
//ConnectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=20;Max Pool Size=20;AllowLoadLocalInfile=true;",
|
||||
//DbType = DbType.MySql,
|
||||
//ConnectionString = "Host=127.0.0.1;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=20",
|
||||
//DbType = DbType.PostgreSQL,
|
||||
IsAutoCloseConnection = true,
|
||||
InitKeyType = InitKeyType.Attribute
|
||||
});
|
||||
//db.Aop.OnLogExecuting = (sql, pars) =>
|
||||
//{
|
||||
// Console.WriteLine(sql);//输出sql,查看执行sql
|
||||
//};
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
class SongContext : DbContext
|
||||
{
|
||||
public DbSet<Song> Songs { get; set; }
|
||||
public DbSet<PatientExamination_2022> PatientExamination_2022s { get; set; }
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
optionsBuilder.UseSqlServer(@"Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=19;Max Pool Size=19;TrustServerCertificate=true");
|
||||
//var connectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=19;Max Pool Size=19";
|
||||
//optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
|
||||
//optionsBuilder.UseNpgsql("Host=127.0.0.1;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=19");
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
//CREATE TABLE [dbo].[PatientExamination_2022] (
|
||||
// [Id] uniqueidentifier NOT NULL,
|
||||
// [CreateTime] datetime NOT NULL,
|
||||
// [ExamKindId] uniqueidentifier NOT NULL,
|
||||
// [ExamKindName] nvarchar(255) COLLATE Chinese_PRC_CI_AS NULL,
|
||||
// [PatientGuid] uniqueidentifier NOT NULL,
|
||||
// [PatientName] nvarchar(255) COLLATE Chinese_PRC_CI_AS NULL,
|
||||
// [AnesthesiaType] int NOT NULL,
|
||||
// [DiaRoomId] uniqueidentifier NULL,
|
||||
// [DiaRoomName] nvarchar(255) COLLATE Chinese_PRC_CI_AS NULL,
|
||||
// [QueueIndex] int NOT NULL,
|
||||
// [QueueNum] int NOT NULL,
|
||||
// [OrderDateTime] datetime NOT NULL,
|
||||
// [TimeType] int NOT NULL,
|
||||
// [SignInTime] datetime NULL,
|
||||
// [StartCheckTime] datetime NULL,
|
||||
// [EndCheckTime] datetime NULL,
|
||||
// [VerifyTime] datetime NULL,
|
||||
// [ReportTime] datetime NULL,
|
||||
// [ExaminationState] int NOT NULL
|
||||
//)
|
||||
[Table("PatientExamination_2022")]
|
||||
class PatientExamination_2022
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
public Guid ExamKindId { get; set; }
|
||||
public string ExamKindName { get; set; }
|
||||
public Guid PatientGuid { get; set; }
|
||||
public string PatientName { get; set; }
|
||||
public int AnesthesiaType { get; set; }
|
||||
public Guid? DiaRoomId { get; set; }
|
||||
public string DiaRoomName { get; set; }
|
||||
public int QueueIndex { get; set; }
|
||||
public int QueueNum { get; set; }
|
||||
public DateTime OrderDateTime { get; set; }
|
||||
public int TimeType { get; set; }
|
||||
public DateTime? SignInTime { get; set; }
|
||||
public DateTime? StartCheckTime { get; set; }
|
||||
public DateTime? EndCheckTime { get; set; }
|
||||
public DateTime? VerifyTime { get; set; }
|
||||
public DateTime? ReportTime { get; set; }
|
||||
public int ExaminationState { get; set; }
|
||||
}
|
||||
|
||||
static void TestFreeSqlSelectPatientExamination_2022()
|
||||
{
|
||||
var list = fsql.Select<PatientExamination_2022>().Limit(40000).ToList();
|
||||
//var list = fsql.Ado.Query<PatientExamination_2022>("select top 40000 * from PatientExamination_2022");
|
||||
}
|
||||
static void TestEfSelectPatientExamination_2022()
|
||||
{
|
||||
using (var ctx = new SongContext())
|
||||
{
|
||||
var list = ctx.PatientExamination_2022s.Take(40000).AsNoTracking().ToList();
|
||||
}
|
||||
}
|
||||
static void TestSqlSugarSelectPatientExamination_2022()
|
||||
{
|
||||
var list = sugar.Queryable<PatientExamination_2022>().Take(40000).ToList();
|
||||
}
|
||||
static void TestDapperSelectPatientExamination_2022()
|
||||
{
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=21;Max Pool Size=22"))
|
||||
{
|
||||
var list = conn.Query<PatientExamination_2022>("select top 40000 * from PatientExamination_2022");
|
||||
}
|
||||
}
|
||||
|
||||
static DbConnection fsqlConn = null;
|
||||
static void Main(string[] args)
|
||||
{
|
||||
//var count = 0;
|
||||
//var sws = new List<long>();
|
||||
//Console.WriteLine("观察查询4万条记录内存,按 Enter 进入下一次,按任易键即出程序。。。");
|
||||
////while(Console.ReadKey().Key == ConsoleKey.Enter)
|
||||
////using (var fcon = fsql.Ado.MasterPool.Get())
|
||||
////{
|
||||
// //fsqlConn = fcon.Value;
|
||||
// for (var a = 0; a < 80; a++)
|
||||
// {
|
||||
// Stopwatch sw = Stopwatch.StartNew();
|
||||
// TestFreeSqlSelectPatientExamination_2022();
|
||||
// //TestEfSelectPatientExamination_2022();
|
||||
// //TestSqlSugarSelectPatientExamination_2022();
|
||||
// //TestDapperSelectPatientExamination_2022();
|
||||
// sw.Stop();
|
||||
// sws.Add(sw.ElapsedMilliseconds);
|
||||
// Console.WriteLine($"第 {++count} 次,查询4万条记录, {sw.ElapsedMilliseconds}ms,平均 {(long)sws.Average()}ms");
|
||||
// }
|
||||
////}
|
||||
//Console.ReadKey();
|
||||
//fsql.Dispose();
|
||||
//return;
|
||||
|
||||
//fsql.CodeFirst.SyncStructure(typeof(Song), typeof(Song_tag), typeof(Tag));
|
||||
//sugar.CodeFirst.InitTables(typeof(Song), typeof(Song_tag), typeof(Tag));
|
||||
//sugar创建表失败:SqlSugar.SqlSugarException: Sequence contains no elements
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song), "freesql_song");
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song), "sugar_song");
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song), "efcore_song");
|
||||
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song_tag), "freesql_song_tag");
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song_tag), "sugar_song_tag");
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song_tag), "efcore_song_tag");
|
||||
|
||||
fsql.CodeFirst.SyncStructure(typeof(Tag), "freesql_tag");
|
||||
fsql.CodeFirst.SyncStructure(typeof(Tag), "sugar_tag");
|
||||
fsql.CodeFirst.SyncStructure(typeof(Tag), "efcore_tag");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
var time = new Stopwatch();
|
||||
|
||||
|
||||
#region ET test
|
||||
////var t31 = fsql.Select<xxx>().ToList();
|
||||
//fsql.Select<Song>().First();
|
||||
|
||||
//time.Restart();
|
||||
//var t3 = fsql.Select<Song>().ToList();
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ToList Entity Counts: {t3.Count}; ORM: FreeSql*");
|
||||
|
||||
//time.Restart();
|
||||
//var adoarr1 = fsql.Ado.ExecuteArray("select * from freesql_song");
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteArray Entity Counts: {adoarr1.Length}; ORM: FreeSql ExecuteArray*");
|
||||
|
||||
//time.Restart();
|
||||
//var adolist1 = new List<Song>();
|
||||
//fsql.Ado.ExecuteReader(dr =>
|
||||
//{
|
||||
// var xim = new Song();
|
||||
// dr.GetValue(0)?.GetType();
|
||||
// dr.GetValue(1)?.GetType();
|
||||
// dr.GetValue(2)?.GetType();
|
||||
// dr.GetValue(3)?.GetType();
|
||||
// dr.GetValue(4)?.GetType();
|
||||
// adolist1.Add(xim);
|
||||
//}, "select * from freesql_song");
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReader Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReader*");
|
||||
|
||||
|
||||
//time.Restart();
|
||||
//adolist1 = new List<Song>();
|
||||
//fsql.Ado.ExecuteReader(dr =>
|
||||
//{
|
||||
// var xim = new Song();
|
||||
// var v1 = dr.GetValue(0);
|
||||
// var locvalue = (object)v1;
|
||||
// if (locvalue == null || locvalue == DBNull.Value) xim.Id = default;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is int iv) xim.Id = iv;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// v1 = dr.GetValue(1);
|
||||
// locvalue = (object)v1;
|
||||
// if (locvalue == null || locvalue == DBNull.Value) xim.Create_time = default;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is DateTime dt) xim.Create_time = dt;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// v1 = dr.GetValue(2);
|
||||
// locvalue = (object)v1;
|
||||
// if (locvalue == null || locvalue == DBNull.Value) xim.Is_deleted = default;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is bool bl) xim.Is_deleted = bl;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// v1 = dr.GetValue(3);
|
||||
// locvalue = (object)v1;
|
||||
// if (locvalue == null || locvalue == DBNull.Value) xim.Title = default;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string str) xim.Title = str;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// v1 = dr.GetValue(4);
|
||||
// locvalue = (object)v1;
|
||||
// if (locvalue == null || locvalue == DBNull.Value) xim.Url = default;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string str) xim.Url = str;
|
||||
// else
|
||||
// {
|
||||
// if (locvalue is string)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// adolist1.Add(xim);
|
||||
//}, "select * from freesql_song");
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReaderObject Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReaderObject*");
|
||||
|
||||
////var type = typeof(Song);
|
||||
////var myfuncParam1 = Expression.Parameter(typeof(object[]), "values");
|
||||
////var retExp = Expression.Variable(type, "ret");
|
||||
////var objExp = Expression.Variable(typeof(object), "obj");
|
||||
////var returnTarget = Expression.Label(type);
|
||||
////var myfuncBody = Expression.Block(
|
||||
//// new[] { retExp, objExp },
|
||||
//// Expression.Assign(retExp, type.InternalNewExpression()),
|
||||
//// Expression.Assign(objExp, Expression.ArrayIndex(myfuncParam1, Expression.Constant(0))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Id").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Id")), Expression.Convert(objExp, type.GetProperty("Id").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.ArrayIndex(myfuncParam1, Expression.Constant(1))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Create_time").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Create_time")), Expression.Convert(objExp, type.GetProperty("Create_time").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.ArrayIndex(myfuncParam1, Expression.Constant(2))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Is_deleted").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Is_deleted")), Expression.Convert(objExp, type.GetProperty("Is_deleted").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.ArrayIndex(myfuncParam1, Expression.Constant(3))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Title").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Title")), Expression.Convert(objExp, type.GetProperty("Title").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.ArrayIndex(myfuncParam1, Expression.Constant(4))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Url").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Url")), Expression.Convert(objExp, type.GetProperty("Url").PropertyType)),
|
||||
//// Expression.Return(returnTarget, retExp),
|
||||
//// Expression.Label(returnTarget, Expression.Default(type))
|
||||
////);
|
||||
////var myfunc = Expression.Lambda<Func<object[], Song>>(myfuncBody, myfuncParam1).Compile();
|
||||
////time.Restart();
|
||||
////adolist1 = new List<Song>();
|
||||
////fsql.Ado.ExecuteReader(dr =>
|
||||
////{
|
||||
//// var values = new object[dr.FieldCount];
|
||||
//// dr.GetValues(values);
|
||||
//// var xim = myfunc(values);
|
||||
//// adolist1.Add(xim);
|
||||
////}, "select * from freesql_song");
|
||||
////time.Stop();
|
||||
////sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReaderMyFunc Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReaderMyFunc*");
|
||||
|
||||
|
||||
////var methodDrgv = typeof(DbDataReader).GetMethod("GetValue");
|
||||
////var myfunc2Param1 = Expression.Parameter(typeof(DbDataReader), "dr");
|
||||
////var myfunc2Body = Expression.Block(
|
||||
//// new[] { retExp, objExp },
|
||||
//// Expression.Assign(retExp, type.InternalNewExpression()),
|
||||
//// Expression.Assign(objExp, Expression.Call(myfunc2Param1, methodDrgv, Expression.Constant(0))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Id").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Id")), Expression.Convert(objExp, type.GetProperty("Id").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.Call(myfunc2Param1, methodDrgv, Expression.Constant(1))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Create_time").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Create_time")), Expression.Convert(objExp, type.GetProperty("Create_time").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.Call(myfunc2Param1, methodDrgv, Expression.Constant(2))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Is_deleted").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Is_deleted")), Expression.Convert(objExp, type.GetProperty("Is_deleted").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.Call(myfunc2Param1, methodDrgv, Expression.Constant(3))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Title").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Title")), Expression.Convert(objExp, type.GetProperty("Title").PropertyType)),
|
||||
//// Expression.Assign(objExp, Expression.Call(myfunc2Param1, methodDrgv, Expression.Constant(4))),
|
||||
//// Utils.GetConvertExpression(type.GetProperty("Url").PropertyType, objExp),
|
||||
//// Expression.Assign(Expression.MakeMemberAccess(retExp, type.GetProperty("Url")), Expression.Convert(objExp, type.GetProperty("Url").PropertyType)),
|
||||
//// Expression.Return(returnTarget, retExp),
|
||||
//// Expression.Label(returnTarget, Expression.Default(type))
|
||||
////);
|
||||
////var myfunc2 = Expression.Lambda<Func<DbDataReader, Song>>(myfunc2Body, myfunc2Param1).Compile();
|
||||
////time.Restart();
|
||||
////adolist1 = new List<Song>();
|
||||
////fsql.Ado.ExecuteReader(dr =>
|
||||
////{
|
||||
//// var xim = myfunc2(dr);
|
||||
//// adolist1.Add(xim);
|
||||
////}, "select * from freesql_song");
|
||||
////time.Stop();
|
||||
////sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReaderMyFunc22 Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReaderMyFunc22*");
|
||||
|
||||
|
||||
//time.Restart();
|
||||
//adolist1 = new List<Song>();
|
||||
//fsql.Ado.ExecuteReader(dr =>
|
||||
//{
|
||||
// var xim = new Song();
|
||||
// dr.GetFieldValue<int>(0);
|
||||
// dr.GetFieldValue<DateTime>(1);
|
||||
// dr.GetFieldValue<bool>(2);
|
||||
// dr.GetFieldValue<string>(3);
|
||||
// dr.GetFieldValue<string>(4);
|
||||
// adolist1.Add(xim);
|
||||
//}, "select * from freesql_song");
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReader0000 Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReader0000*");
|
||||
|
||||
//time.Restart();
|
||||
//adolist1 = new List<Song>();
|
||||
//fsql.Ado.ExecuteReader(dr =>
|
||||
//{
|
||||
// var xim = new Song();
|
||||
// Utils.GetDataReaderValue(typeof(int), dr.GetValue(0));
|
||||
// Utils.GetDataReaderValue(typeof(DateTime), dr.GetValue(1));
|
||||
// Utils.GetDataReaderValue(typeof(bool), dr.GetValue(2));
|
||||
// Utils.GetDataReaderValue(typeof(string), dr.GetValue(3));
|
||||
// Utils.GetDataReaderValue(typeof(string), dr.GetValue(4));
|
||||
// adolist1.Add(xim);
|
||||
//}, "select * from freesql_song");
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReader1111 Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReader1111*");
|
||||
|
||||
|
||||
////time.Restart();
|
||||
////adolist1 = new List<Song>();
|
||||
////fsql.Ado.ExecuteReader(dr =>
|
||||
////{
|
||||
//// var xim = new Song();
|
||||
//// Utils.GetConvertValue(typeof(int), dr.GetValue(0));
|
||||
//// Utils.GetConvertValue(typeof(DateTime), dr.GetValue(1));
|
||||
//// Utils.GetConvertValue(typeof(bool), dr.GetValue(2));
|
||||
//// Utils.GetConvertValue(typeof(string), dr.GetValue(3));
|
||||
//// Utils.GetConvertValue(typeof(string), dr.GetValue(4));
|
||||
//// adolist1.Add(xim);
|
||||
////}, "select * from freesql_song");
|
||||
////time.Stop();
|
||||
////sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReader11112222 Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReader11112222*");
|
||||
|
||||
|
||||
//time.Restart();
|
||||
//adolist1 = new List<Song>();
|
||||
//fsql.Ado.ExecuteReader(dr =>
|
||||
//{
|
||||
// var values = new object[dr.FieldCount];
|
||||
// dr.GetValues(values);
|
||||
|
||||
// var xim = new Song();
|
||||
// xim.Id = (int)Utils.GetDataReaderValue(typeof(int), values[0]);
|
||||
// xim.Create_time = (DateTime)Utils.GetDataReaderValue(typeof(DateTime), values[1]);
|
||||
// xim.Is_deleted = (bool)Utils.GetDataReaderValue(typeof(bool), values[2]);
|
||||
// xim.Title = (string)Utils.GetDataReaderValue(typeof(string), values[3]);
|
||||
// xim.Url = (string)Utils.GetDataReaderValue(typeof(string), values[4]);
|
||||
// adolist1.Add(xim);
|
||||
//}, "select * from freesql_song");
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReader1111 Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReader1111*");
|
||||
|
||||
|
||||
////time.Restart();
|
||||
////adolist1 = new List<Song>();
|
||||
////fsql.Ado.ExecuteReader(dr =>
|
||||
////{
|
||||
//// var values = new object[dr.FieldCount];
|
||||
//// dr.GetValues(values);
|
||||
|
||||
//// var xim = new Song();
|
||||
//// xim.Id = (int)Utils.GetConvertValue(typeof(int), values[0]);
|
||||
//// xim.Create_time = (DateTime)Utils.GetConvertValue(typeof(DateTime), values[1]);
|
||||
//// xim.Is_deleted = (bool)Utils.GetConvertValue(typeof(bool), values[2]);
|
||||
//// xim.Title = (string)Utils.GetConvertValue(typeof(string), values[3]);
|
||||
//// xim.Url = (string)Utils.GetConvertValue(typeof(string), values[4]);
|
||||
//// adolist1.Add(xim);
|
||||
////}, "select * from freesql_song");
|
||||
////time.Stop();
|
||||
////sb.AppendLine($"Elapsed: {time.Elapsed}; ExecuteReader11112222 Entity Counts: {adolist1.Count}; ORM: FreeSql ExecuteReader11112222*");
|
||||
|
||||
|
||||
//time.Restart();
|
||||
//List<Song> dplist1 = null;
|
||||
//using (var conn = fsql.Ado.MasterPool.Get())
|
||||
//{
|
||||
// dplist1 = Dapper.SqlMapper.Query<Song>(conn.Value, "select * from freesql_song").ToList();
|
||||
//}
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {dplist1.Count}; ORM: Dapper");
|
||||
|
||||
//time.Restart();
|
||||
//t3 = fsql.Select<Song>().ToList();
|
||||
//time.Stop();
|
||||
//sb.AppendLine($"Elapsed: {time.Elapsed}; ToList Entity Counts: {t3.Count}; ORM: FreeSql*");
|
||||
|
||||
//Console.WriteLine(sb.ToString());
|
||||
//Console.ReadKey();
|
||||
|
||||
#endregion
|
||||
|
||||
sugar.Aop.OnLogExecuted = (s, e) =>
|
||||
{
|
||||
Trace.WriteLine(s);
|
||||
};
|
||||
//测试前清空数据
|
||||
fsql.Delete<Song>().Where(a => a.id > 0).ExecuteAffrows();
|
||||
sugar.Deleteable<Song>().Where(a => a.id > 0).ExecuteCommand();
|
||||
fsql.Ado.ExecuteNonQuery("delete from efcore_song");
|
||||
|
||||
Console.WriteLine("插入性能:");
|
||||
Insert(sb, 100, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 100, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Insert(sb, 1, 1000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1, 10000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1, 50000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1, 100000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("查询性能:");
|
||||
Select(sb, 100, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 100, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Select(sb, 1, 1000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1, 10000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1, 50000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1, 100000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("更新:");
|
||||
Update(sb, 10, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 10, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Update(sb, 1, 1000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1, 10000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1, 50000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1, 100000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("测试结束,按任意键退出...");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
static void Select(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
fsql.Select<Song>().Limit(size).ToList();
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
sugar.Queryable<Song>().Take(size).ToList();
|
||||
sw.Stop();
|
||||
sb.AppendLine($"SqlSugar Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Songs.Take(size).AsNoTracking().ToList();
|
||||
}
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"EFCore Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms .net5.0无效");
|
||||
|
||||
//sw.Restart();
|
||||
//using (var conn = fsql.Ado.MasterPool.Get())
|
||||
//{
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// Dapper.SqlMapper.Query<Song>(conn.Value, $"select * from freesql_song limit {size}").ToList();
|
||||
//}
|
||||
//sw.Stop();
|
||||
//sb.AppendLine($"Dapper Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms\r\n");
|
||||
}
|
||||
|
||||
static void Insert(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
var songs = Enumerable.Range(0, size).Select(a => new Song
|
||||
{
|
||||
create_time = DateTime.Now.ToString(),
|
||||
is_deleted = false,
|
||||
title = $"Insert_{a}",
|
||||
url = $"Url_{a}"
|
||||
});
|
||||
|
||||
//预热
|
||||
fsql.Insert(songs.First()).ExecuteAffrows();
|
||||
sugar.Insertable(songs.First()).ExecuteCommand();
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
//db.Songs.AddRange(songs.First());
|
||||
//db.SaveChanges(); //.net5.0 throw Microsoft.EntityFrameworkCore.DbUpdateException
|
||||
}
|
||||
Stopwatch sw = new Stopwatch();
|
||||
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
fsql.Insert(songs).ExecuteAffrows();
|
||||
//using (var db = new FreeSongContext()) {
|
||||
// //db.Configuration.AutoDetectChangesEnabled = false;
|
||||
// db.Songs.AddRange(songs.ToArray());
|
||||
// db.SaveChanges();
|
||||
//}
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Insert {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
sw.Restart();
|
||||
Exception sugarEx = null;
|
||||
try
|
||||
{
|
||||
for (var a = 0; a < forTime; a++)
|
||||
//sugar.Fastest<Song>().BulkCopy(songs.ToList());
|
||||
sugar.Insertable(songs.ToArray()).ExecuteCommand();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sugarEx = ex;
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"SqlSugar Insert {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms" + (sugarEx != null ? $"成绩无效,错误:{sugarEx.Message}" : ""));
|
||||
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
//db.Songs.AddRange(songs.ToArray());
|
||||
//db.SaveChanges(); //.net5.0 throw Microsoft.EntityFrameworkCore.DbUpdateException
|
||||
}
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"EFCore Insert {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms .net5.0无效\r\n");
|
||||
}
|
||||
|
||||
static void Update(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
|
||||
var songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
fsql.Update<Song>().SetSource(songs).ExecuteAffrows();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Update1 {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
|
||||
songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
fsql.Update<Song>().SetSource(songs).ExecuteSqlBulkCopy();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql BulkCopyUpdate {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
// songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
// sw.Restart();
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// {
|
||||
// //fsql.Update<Song>().SetSource(songs).ExecuteAffrows();
|
||||
// var iou = fsql.InsertOrUpdate<Song>() as InsertOrUpdateProvider<Song>;
|
||||
// var dbsql = new StringBuilder();
|
||||
// var dbparms = new List<DbParameter>();
|
||||
// iou.WriteSourceSelectUnionAll(songs, dbsql, dbparms);
|
||||
|
||||
// var sql = $@"update freesql_song a
|
||||
//inner join ( {dbsql} ) b on b.id = a.id
|
||||
//set a.create_time = b.create_time, a.is_deleted = b.is_deleted, a.title = b.title, a.url = b.url";
|
||||
// fsql.Ado.ExecuteNonQuery(System.Data.CommandType.Text, sql, dbparms.ToArray());
|
||||
// }
|
||||
// sw.Stop();
|
||||
// sb.AppendLine($"FreeSql Update2(update inner join) {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
// songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
// sw.Restart();
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// {
|
||||
// var isdroped = false;
|
||||
// var tempTableName = $"#Temp_freesql_song";
|
||||
// fsql.Ado.ExecuteNonQuery($"select * into {tempTableName} from [freesql_song] where 1=2");
|
||||
// try
|
||||
// {
|
||||
// fsql.Insert(songs).AsTable(tempTableName).ExecuteMySqlBulkCopy();
|
||||
// var sql = $@"update freesql_song a
|
||||
//inner join {tempTableName} b on b.id = a.id;
|
||||
//set a.create_time = b.create_time, a.is_deleted = b.is_deleted, a.title = b.title, a.url = b.url
|
||||
//; drop table {tempTableName}; ";
|
||||
// fsql.Ado.ExecuteNonQuery(System.Data.CommandType.Text, sql);
|
||||
// isdroped = true;
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// if (isdroped == false)
|
||||
// fsql.Ado.ExecuteNonQuery($"drop table {tempTableName}");
|
||||
// }
|
||||
// }
|
||||
// sw.Stop();
|
||||
// sb.AppendLine($"FreeSql Update3(update inner join #temp) {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
songs = sugar.Queryable<Song>().Take(size).ToList();
|
||||
sw.Restart();
|
||||
Exception sugarEx = null;
|
||||
try
|
||||
{
|
||||
for (var a = 0; a < forTime; a++)
|
||||
sugar.Fastest<Song>().BulkUpdate(songs);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sugarEx = ex;
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"SqlSugar Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms" + (sugarEx != null ? $"成绩无效,错误:{sugarEx.Message}" : ""));
|
||||
|
||||
//using (var db = new SongContext())
|
||||
//{
|
||||
// songs = db.Songs.Take(size).AsNoTracking().ToList();
|
||||
//}
|
||||
//sw.Restart();
|
||||
//for (var a = 0; a < forTime; a++)
|
||||
//{
|
||||
|
||||
// using (var db = new SongContext())
|
||||
// {
|
||||
// //db.Configuration.AutoDetectChangesEnabled = false;
|
||||
// //db.Songs.UpdateRange(songs.ToArray());
|
||||
// //db.SaveChanges();
|
||||
// }
|
||||
//}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"EFCore Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms .net5.0无效\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_song")]
|
||||
[SugarTable("sugar_song")]
|
||||
[Table("efcore_song")]
|
||||
public class Song
|
||||
{
|
||||
[FreeSql.DataAnnotations.Column(IsIdentity = true)]
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int id { get; set; }
|
||||
public string create_time { get; set; }
|
||||
public bool? is_deleted { get; set; }
|
||||
public string title { get; set; }
|
||||
public string url { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
[NotMapped]
|
||||
public virtual ICollection<Tag> Tags { get; set; }
|
||||
}
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_song_tag")]
|
||||
[SugarTable("sugar_song_tag")]
|
||||
[Table("efcore_song_tag")]
|
||||
public class Song_tag
|
||||
{
|
||||
public int song_id { get; set; }
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
[NotMapped]
|
||||
public virtual Song Song { get; set; }
|
||||
|
||||
public int tag_id { get; set; }
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
[NotMapped]
|
||||
public virtual Tag Tag { get; set; }
|
||||
}
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_tag")]
|
||||
[SugarTable("sugar_tag")]
|
||||
[Table("efcore_tag")]
|
||||
public class Tag
|
||||
{
|
||||
[FreeSql.DataAnnotations.Column(IsIdentity = true)]
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int id { get; set; }
|
||||
public int? parent_id { get; set; }
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
[NotMapped]
|
||||
public virtual Tag Parent { get; set; }
|
||||
|
||||
public decimal? ddd { get; set; }
|
||||
public string name { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
[NotMapped]
|
||||
public virtual ICollection<Song> Songs { get; set; }
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
[NotMapped]
|
||||
public virtual ICollection<Tag> Tags { get; set; }
|
||||
}
|
||||
}
|
21
Examples/orm_vs/orm_vs.csproj
Normal file
21
Examples/orm_vs/orm_vs.csproj
Normal file
@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
|
||||
<PackageReference Include="sqlSugarCore" Version="5.1.3.38" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
264
Examples/orm_vs_net40/Program.cs
Normal file
264
Examples/orm_vs_net40/Program.cs
Normal file
@ -0,0 +1,264 @@
|
||||
//using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace orm_vs
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=20")
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=20")
|
||||
.UseConnectionString(FreeSql.DataType.Sqlite, "data source=test1.db;max pool size=5")
|
||||
.UseAutoSyncStructure(false)
|
||||
.UseNoneCommandParameter(true)
|
||||
//.UseConfigEntityFromDbFirst(true)
|
||||
.Build();
|
||||
|
||||
//static SqlSugarClient sugar
|
||||
//{
|
||||
// get => new SqlSugarClient(new ConnectionConfig()
|
||||
// {
|
||||
// //不欺负,让连接池100个最小
|
||||
// //ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Min Pool Size=20;Max Pool Size=20",
|
||||
// //DbType = DbType.SqlServer,
|
||||
// ConnectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=20;Max Pool Size=20",
|
||||
// DbType = DbType.MySql,
|
||||
// IsAutoCloseConnection = true,
|
||||
// InitKeyType = InitKeyType.Attribute
|
||||
// });
|
||||
//}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
fsql.CodeFirst.SyncStructure(typeof(Song), typeof(Song_tag), typeof(Tag));
|
||||
//sugar.CodeFirst.InitTables(typeof(Song), typeof(Song_tag), typeof(Tag));
|
||||
//sugar创建表失败:SqlSugar.SqlSugarException: Sequence contains no elements
|
||||
|
||||
//sugar.Aop.OnLogExecuted = (s, e) =>
|
||||
//{
|
||||
// Trace.WriteLine(s);
|
||||
//};
|
||||
//测试前清空数据
|
||||
fsql.Delete<Song>().Where(a => a.Id > 0).ExecuteAffrows();
|
||||
//sugar.Deleteable<Song>().Where(a => a.Id > 0).ExecuteCommand();
|
||||
fsql.Ado.ExecuteNonQuery("delete from efcore_song");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
Console.WriteLine("插入性能:");
|
||||
Insert(sb, 1000, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1000, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Insert(sb, 1, 1000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1, 10000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1, 50000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Insert(sb, 1, 100000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("查询性能:");
|
||||
Select(sb, 1000, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1000, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Select(sb, 1, 1000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1, 10000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1, 50000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Select(sb, 1, 100000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("更新:");
|
||||
Update(sb, 1000, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1000, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Update(sb, 1, 1000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1, 10000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1, 50000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 1, 100000);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("测试结束,按任意键退出...");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
static void Select(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
fsql.Select<Song>().Limit(size).ToList();
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
//sw.Restart();
|
||||
//for (var a = 0; a < forTime; a++)
|
||||
// sugar.Queryable<Song>().Take(size).ToList();
|
||||
//sw.Stop();
|
||||
//sb.AppendLine($"SqlSugar Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
sw.Restart();
|
||||
using (var conn = fsql.Ado.MasterPool.Get())
|
||||
{
|
||||
for (var a = 0; a < forTime; a++)
|
||||
Dapper.SqlMapper.Query<Song>(conn.Value, $"select top {size} * from freesql_song").ToList();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"Dapper Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
}
|
||||
|
||||
static void Insert(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
var songs = Enumerable.Range(0, size).Select(a => new Song
|
||||
{
|
||||
Create_time = DateTime.Now,
|
||||
Is_deleted = false,
|
||||
Title = $"Insert_{a}",
|
||||
Url = $"Url_{a}"
|
||||
});
|
||||
|
||||
//预热
|
||||
fsql.Insert(songs.First()).ExecuteAffrows();
|
||||
//sugar.Insertable(songs.First()).ExecuteCommand();
|
||||
Stopwatch sw = new Stopwatch();
|
||||
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
fsql.Insert(songs).ExecuteAffrows();
|
||||
//using (var db = new FreeSongContext()) {
|
||||
// //db.Configuration.AutoDetectChangesEnabled = false;
|
||||
// db.Songs.AddRange(songs.ToArray());
|
||||
// db.SaveChanges();
|
||||
//}
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Insert {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
//sw.Restart();
|
||||
//Exception sugarEx = null;
|
||||
//try
|
||||
//{
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// sugar.Insertable(songs.ToArray()).ExecuteCommand();
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// sugarEx = ex;
|
||||
//}
|
||||
//sw.Stop();
|
||||
//sb.AppendLine($"SqlSugar Insert {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms" + (sugarEx != null ? $"成绩无效,错误:{sugarEx.Message}" : ""));
|
||||
}
|
||||
|
||||
static void Update(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
|
||||
var songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
fsql.Update<Song>().SetSource(songs).ExecuteAffrows();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
//songs = sugar.Queryable<Song>().Take(size).ToList();
|
||||
//sw.Restart();
|
||||
//Exception sugarEx = null;
|
||||
//try
|
||||
//{
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// sugar.Updateable(songs).ExecuteCommand();
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// sugarEx = ex;
|
||||
//}
|
||||
//sw.Stop();
|
||||
//sb.AppendLine($"SqlSugar Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms" + (sugarEx != null ? $"成绩无效,错误:{sugarEx.Message}" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_song")]
|
||||
//[SugarTable("sugar_song")]
|
||||
public class Song
|
||||
{
|
||||
[FreeSql.DataAnnotations.Column(IsIdentity = true)]
|
||||
//[SugarColumn(IsPrimaryKey = true, 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; }
|
||||
|
||||
//[SugarColumn(IsIgnore = true)]
|
||||
public virtual ICollection<Tag> Tags { get; set; }
|
||||
}
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_song_tag")]
|
||||
//[SugarTable("sugar_song_tag")]
|
||||
public class Song_tag
|
||||
{
|
||||
public int Song_id { get; set; }
|
||||
//[SugarColumn(IsIgnore = true)]
|
||||
public virtual Song Song { get; set; }
|
||||
|
||||
public int Tag_id { get; set; }
|
||||
//[SugarColumn(IsIgnore = true)]
|
||||
public virtual Tag Tag { get; set; }
|
||||
}
|
||||
[FreeSql.DataAnnotations.Table(Name = "freesql_tag")]
|
||||
//[SugarTable("sugar_tag")]
|
||||
public class Tag
|
||||
{
|
||||
[FreeSql.DataAnnotations.Column(IsIdentity = true)]
|
||||
//[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
public int? Parent_id { get; set; }
|
||||
//[SugarColumn(IsIgnore = true)]
|
||||
public virtual Tag Parent { get; set; }
|
||||
|
||||
public decimal? Ddd { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
//[SugarColumn(IsIgnore = true)]
|
||||
public virtual ICollection<Song> Songs { get; set; }
|
||||
//[SugarColumn(IsIgnore = true)]
|
||||
public virtual ICollection<Tag> Tags { get; set; }
|
||||
}
|
||||
}
|
36
Examples/orm_vs_net40/Properties/AssemblyInfo.cs
Normal file
36
Examples/orm_vs_net40/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("orm_vs_net40")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("orm_vs_net40")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("1674bce3-eeb4-4003-a2a7-06f51efaea23")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
79
Examples/orm_vs_net40/orm_vs_net40.csproj
Normal file
79
Examples/orm_vs_net40/orm_vs_net40.csproj
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>orm_vs_net40</RootNamespace>
|
||||
<AssemblyName>orm_vs_net40</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj">
|
||||
<Project>{af9c50ec-6eb6-494b-9b3b-7edba6fd0ebb}</Project>
|
||||
<Name>FreeSql</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySql\FreeSql.Provider.MySql.csproj">
|
||||
<Project>{28c6a39c-7ae7-4210-b7b0-0970216637a8}</Project>
|
||||
<Name>FreeSql.Provider.MySql</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj">
|
||||
<Project>{559b6369-1868-4a06-a590-f80ba7b80a1b}</Project>
|
||||
<Name>FreeSql.Provider.Sqlite</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj">
|
||||
<Project>{b61aac9e-59e9-4f47-bbe3-97ac24112efe}</Project>
|
||||
<Name>FreeSql.Provider.SqlServer</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper">
|
||||
<Version>1.50.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>13.0.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\.editorconfig">
|
||||
<Link>.editorconfig</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
115
Examples/repository_01/Controllers/SongController.cs
Normal file
115
Examples/repository_01/Controllers/SongController.cs
Normal file
@ -0,0 +1,115 @@
|
||||
using FreeSql;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using repository_01;
|
||||
using restful.Entitys;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace restful.Controllers
|
||||
{
|
||||
|
||||
public class SongRepository : GuidRepository<Song>
|
||||
{
|
||||
public SongRepository(IFreeSql fsql) : base(fsql)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Route("restapi/[controller]")]
|
||||
public class SongsController : Controller
|
||||
{
|
||||
|
||||
BaseRepository<Song, int> _songRepository;
|
||||
|
||||
public class xxxx
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public bool IsDeleted { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public SongsController(IFreeSql fsql,
|
||||
BaseRepository<Song> repos3, BaseRepository<Song, int> repos4,
|
||||
IBaseRepository<Song> repos31, IBaseRepository<Song, int> repos41,
|
||||
|
||||
SongRepository reposSong,
|
||||
IBaseRepository<TestSoftDelete> reposTest
|
||||
)
|
||||
{
|
||||
Console.Write(reposTest.Select.ToSql());
|
||||
|
||||
_songRepository = repos4;
|
||||
//test code
|
||||
var curd1 = fsql.GetRepository<Song, int>();
|
||||
var curd2 = fsql.GetRepository<Song, string>();
|
||||
var curd3 = fsql.GetRepository<Song, Guid>();
|
||||
var curd4 = fsql.GetGuidRepository<Song>();
|
||||
|
||||
Console.WriteLine(reposSong.Select.ToSql());
|
||||
|
||||
using (reposSong.DataFilter.DisableAll())
|
||||
{
|
||||
Console.WriteLine(reposSong.Select.ToSql());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public Task<List<Song>> GetItems([FromQuery] string key, [FromQuery] int page = 1, [FromQuery] int limit = 20)
|
||||
{
|
||||
return _songRepository.Select.WhereIf(!string.IsNullOrEmpty(key), a => a.Title.Contains(key)).Page(page, limit).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// curl -X GET "http://localhost:5000/restapi/Songs/GetPagingItems?key=FreeSql&PageNumber=2&PageSize=10" -H "accept: text/plain"
|
||||
/// </summary>
|
||||
/// <param name="pagingInfo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("GetPagingItems")]
|
||||
public Task<List<Song>> GetPagingItems([FromQuery] string key, [FromQuery] PagingInfo pagingInfo)
|
||||
{
|
||||
return _songRepository.Select.WhereIf(!string.IsNullOrEmpty(key), a => a.Title.Contains(key)).Page(pagingInfo).ToListAsync();
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public Task<Song> GetItem([FromRoute] int id)
|
||||
{
|
||||
return _songRepository.FindAsync(id);
|
||||
}
|
||||
|
||||
public class ModelSong
|
||||
{
|
||||
public string title { get; set; }
|
||||
}
|
||||
|
||||
[HttpPost, ProducesResponseType(201)]
|
||||
public Task<Song> Create([FromBody] ModelSong model)
|
||||
{
|
||||
return _songRepository.InsertAsync(new Song { Title = model.title });
|
||||
}
|
||||
|
||||
[HttpPut("{id}")]
|
||||
public Task Update([FromRoute] int id, [FromBody] ModelSong model)
|
||||
{
|
||||
return _songRepository.UpdateAsync(new Song { Id = id, Title = model.title });
|
||||
}
|
||||
|
||||
[HttpPatch("{id}")]
|
||||
async public Task<Song> UpdateDiy([FromRoute] int id, [FromForm] string title)
|
||||
{
|
||||
var up = _songRepository.UpdateDiy.Where(a => a.Id == id);
|
||||
if (!string.IsNullOrEmpty(title)) up.Set(a => a.Title, title);
|
||||
var ret = await up.ExecuteUpdatedAsync();
|
||||
return ret.FirstOrDefault();
|
||||
}
|
||||
|
||||
[HttpDelete("{id}"), ProducesResponseType(204)]
|
||||
public Task Delete([FromRoute] int id)
|
||||
{
|
||||
return _songRepository.DeleteAsync(a => a.Id == id);
|
||||
}
|
||||
}
|
||||
}
|
13
Examples/repository_01/Entitys/Song.cs
Normal file
13
Examples/repository_01/Entitys/Song.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using repository_01;
|
||||
|
||||
namespace restful.Entitys
|
||||
{
|
||||
public class Song
|
||||
{
|
||||
|
||||
[Column(IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
57
Examples/repository_01/PagingInfo.cs
Normal file
57
Examples/repository_01/PagingInfo.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace repository_01
|
||||
{
|
||||
public class PagingInfo : BasePagingInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 无参构造函数
|
||||
/// </summary>
|
||||
public PagingInfo()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 当前为第1页,每页大小的构造函数
|
||||
/// </summary>
|
||||
/// <param name="pageSize"></param>
|
||||
public PagingInfo(int pageSize)
|
||||
{
|
||||
PageNumber = 1;
|
||||
PageSize = pageSize;
|
||||
}
|
||||
/// <summary>
|
||||
/// 带当前页和每页大小的构造函数
|
||||
/// </summary>
|
||||
/// <param name="pageNumber"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
public PagingInfo(int pageNumber, int pageSize)
|
||||
{
|
||||
PageNumber = pageNumber;
|
||||
PageSize = pageSize;
|
||||
}
|
||||
/// <summary>
|
||||
/// 当前有多少页【只读】
|
||||
/// </summary>
|
||||
public long PageCount => PageSize == 0 ? 0 : (Count + PageSize - 1) / PageSize;
|
||||
/// <summary>
|
||||
/// 是否有上一页【只读】
|
||||
/// </summary>
|
||||
public bool HasPrevious => PageNumber > 1 && PageNumber <= PageCount;
|
||||
/// <summary>
|
||||
/// 是否有下一页【只读】
|
||||
/// </summary>
|
||||
public bool HasNext => PageNumber < PageCount;
|
||||
/// <summary>
|
||||
/// 是否在第一页【只读】
|
||||
/// </summary>
|
||||
public bool IsFrist => PageNumber == 1;
|
||||
/// <summary>
|
||||
/// 是否在最后一页【只读】
|
||||
/// </summary>
|
||||
public bool IsLast => PageNumber == PageCount;
|
||||
}
|
||||
}
|
24
Examples/repository_01/Program.cs
Normal file
24
Examples/repository_01/Program.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace repository_01
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
27
Examples/repository_01/Properties/launchSettings.json
Normal file
27
Examples/repository_01/Properties/launchSettings.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:52751/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"repository_01": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:52752/"
|
||||
}
|
||||
}
|
||||
}
|
95
Examples/repository_01/Startup.cs
Normal file
95
Examples/repository_01/Startup.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace repository_01
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 用户密码信息
|
||||
/// </summary>
|
||||
public class Sys1UserLogOn
|
||||
{
|
||||
[Column(IsPrimary = true, Name = "Id")]
|
||||
public Guid UserLogOnId { get; set; }
|
||||
public virtual Sys1User User { get; set; }
|
||||
}
|
||||
public class Sys1User
|
||||
{
|
||||
[Column(IsPrimary = true, Name = "Id")]
|
||||
public Guid UserId { get; set; }
|
||||
public virtual Sys1UserLogOn UserLogOn { get; set; }
|
||||
}
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
|
||||
{
|
||||
Configuration = configuration;
|
||||
|
||||
Fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10")
|
||||
.UseAutoSyncStructure(true)
|
||||
.UseLazyLoading(true)
|
||||
|
||||
.UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
|
||||
.Build();
|
||||
|
||||
var sysu = new Sys1User { };
|
||||
Fsql.Insert<Sys1User>().AppendData(sysu).ExecuteAffrows();
|
||||
Fsql.Insert<Sys1UserLogOn>().AppendData(new Sys1UserLogOn { UserLogOnId = sysu.UserId }).ExecuteAffrows();
|
||||
var a = Fsql.Select<Sys1UserLogOn>().ToList();
|
||||
var b = Fsql.Select<Sys1UserLogOn>().Any();
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public static IFreeSql Fsql { get; private set; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
//services.AddTransient(s => s.)
|
||||
|
||||
services.AddControllersWithViews();
|
||||
services.AddSingleton<IFreeSql>(Fsql);
|
||||
|
||||
services.AddFreeRepository(filter =>
|
||||
{
|
||||
filter
|
||||
//.Apply<Song>("test", a => a.Title == DateTime.Now.ToString() + System.Threading.Thread.CurrentThread.ManagedThreadId)
|
||||
.Apply<ISoftDelete>("softdelete", a => a.IsDeleted == false);
|
||||
}, this.GetType().Assembly);
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
Console.OutputEncoding = Encoding.GetEncoding("GB2312");
|
||||
Console.InputEncoding = Encoding.GetEncoding("GB2312");
|
||||
|
||||
app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(a => a.MapControllers());
|
||||
}
|
||||
}
|
||||
|
||||
public interface ISoftDelete
|
||||
{
|
||||
bool IsDeleted { get; set; }
|
||||
}
|
||||
|
||||
public class TestSoftDelete : ISoftDelete
|
||||
{
|
||||
[Column(IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
}
|
||||
}
|
9
Examples/repository_01/appsettings.Development.json
Normal file
9
Examples/repository_01/appsettings.Development.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Warning",
|
||||
"Microsoft": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
8
Examples/repository_01/appsettings.json
Normal file
8
Examples/repository_01/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
18
Examples/repository_01/repository_01.csproj
Normal file
18
Examples/repository_01/repository_01.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" />
|
||||
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
BIN
Examples/restful/001.png
Normal file
BIN
Examples/restful/001.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
Examples/restful/002.png
Normal file
BIN
Examples/restful/002.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
Examples/restful/003.png
Normal file
BIN
Examples/restful/003.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
Examples/restful/004.png
Normal file
BIN
Examples/restful/004.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
81
Examples/restful/Controllers/SongController.cs
Normal file
81
Examples/restful/Controllers/SongController.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using restful.Entitys;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace restful.Controllers
|
||||
{
|
||||
|
||||
|
||||
[Route("restapi/[controller]")]
|
||||
public class SongsController : Controller
|
||||
{
|
||||
|
||||
IFreeSql _fsql;
|
||||
|
||||
public SongsController(IFreeSql fsql)
|
||||
{
|
||||
_fsql = fsql;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public Task<List<Song>> GetItems([FromQuery] string key, [FromQuery] int page = 1, [FromQuery] int limit = 20)
|
||||
{
|
||||
return _fsql.Select<Song>().WhereIf(!string.IsNullOrEmpty(key), a => a.Title.Contains(key)).Page(page, limit).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// curl -X GET "http://localhost:5000/restapi/Songs/GetPagingItems?key=FreeSql&PageNumber=2&PageSize=10" -H "accept: text/plain"
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="pagingInfo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("GetPagingItems")]
|
||||
public Task<List<Song>> GetPagingItems([FromQuery] string key, [FromQuery] PagingInfo pagingInfo)
|
||||
{
|
||||
return _fsql.Select<Song>().WhereIf(!string.IsNullOrEmpty(key), a => a.Title.Contains(key)).Page(pagingInfo).ToListAsync();
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public Task<Song> GetItem([FromRoute] int id)
|
||||
{
|
||||
return _fsql.Select<Song>().Where(a => a.Id == id).ToOneAsync();
|
||||
}
|
||||
|
||||
public class ModelSong
|
||||
{
|
||||
public string title { get; set; }
|
||||
}
|
||||
|
||||
[HttpPost, ProducesResponseType(201)]
|
||||
async public Task<Song> Create([FromBody] ModelSong model)
|
||||
{
|
||||
var ret = await _fsql.Insert<Song>().AppendData(new Song { Title = model.title }).ExecuteInsertedAsync();
|
||||
return ret.FirstOrDefault();
|
||||
}
|
||||
|
||||
[HttpPut("{id}")]
|
||||
async public Task<Song> Update([FromRoute] int id, [FromBody] ModelSong model)
|
||||
{
|
||||
var ret = await _fsql.Update<Song>().SetSource(new Song { Id = id, Title = model.title }).ExecuteUpdatedAsync();
|
||||
return ret.FirstOrDefault();
|
||||
}
|
||||
|
||||
[HttpPatch("{id}")]
|
||||
async public Task<Song> UpdateDiy([FromRoute] int id, [FromForm] string title)
|
||||
{
|
||||
var up = _fsql.Update<Song>().Where(a => a.Id == id);
|
||||
if (!string.IsNullOrEmpty(title)) up.Set(a => a.Title, title);
|
||||
var ret = await up.ExecuteUpdatedAsync();
|
||||
return ret.FirstOrDefault();
|
||||
}
|
||||
|
||||
[HttpDelete("{id}"), ProducesResponseType(204)]
|
||||
async public Task<Song> Delete([FromRoute] int id)
|
||||
{
|
||||
var ret = await _fsql.Delete<Song>().Where(a => a.Id == id).ExecuteDeletedAsync();
|
||||
return ret.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
12
Examples/restful/Entitys/Song.cs
Normal file
12
Examples/restful/Entitys/Song.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace restful.Entitys
|
||||
{
|
||||
public class Song
|
||||
{
|
||||
|
||||
[Column(IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
57
Examples/restful/PagingInfo.cs
Normal file
57
Examples/restful/PagingInfo.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace restful
|
||||
{
|
||||
public class PagingInfo : BasePagingInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 无参构造函数
|
||||
/// </summary>
|
||||
public PagingInfo()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 当前为第1页,每页大小的构造函数
|
||||
/// </summary>
|
||||
/// <param name="pageSize"></param>
|
||||
public PagingInfo(int pageSize)
|
||||
{
|
||||
PageNumber = 1;
|
||||
PageSize = pageSize;
|
||||
}
|
||||
/// <summary>
|
||||
/// 带当前页和每页大小的构造函数
|
||||
/// </summary>
|
||||
/// <param name="pageNumber"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
public PagingInfo(int pageNumber, int pageSize)
|
||||
{
|
||||
PageNumber = pageNumber;
|
||||
PageSize = pageSize;
|
||||
}
|
||||
/// <summary>
|
||||
/// 当前有多少页【只读】
|
||||
/// </summary>
|
||||
public long PageCount => PageSize == 0 ? 0 : (Count + PageSize - 1) / PageSize;
|
||||
/// <summary>
|
||||
/// 是否有上一页【只读】
|
||||
/// </summary>
|
||||
public bool HasPrevious => PageNumber > 1 && PageNumber <= PageCount;
|
||||
/// <summary>
|
||||
/// 是否有下一页【只读】
|
||||
/// </summary>
|
||||
public bool HasNext => PageNumber < PageCount;
|
||||
/// <summary>
|
||||
/// 是否在第一页【只读】
|
||||
/// </summary>
|
||||
public bool IsFrist => PageNumber == 1;
|
||||
/// <summary>
|
||||
/// 是否在最后一页【只读】
|
||||
/// </summary>
|
||||
public bool IsLast => PageNumber == PageCount;
|
||||
}
|
||||
}
|
24
Examples/restful/Program.cs
Normal file
24
Examples/restful/Program.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace restful
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
27
Examples/restful/Properties/launchSettings.json
Normal file
27
Examples/restful/Properties/launchSettings.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:49778/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"FreeSql.RESTful.Demo": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:49779/"
|
||||
}
|
||||
}
|
||||
}
|
57
Examples/restful/Startup.cs
Normal file
57
Examples/restful/Startup.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace restful
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
|
||||
{
|
||||
Configuration = configuration;
|
||||
|
||||
Fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10")
|
||||
.UseAutoSyncStructure(true)
|
||||
.Build();
|
||||
|
||||
Fsql.Aop.CurdAfter += (s, e) =>
|
||||
{
|
||||
if (e.ElapsedMilliseconds > 200)
|
||||
{
|
||||
//记录日志
|
||||
//发送短信给负责人
|
||||
}
|
||||
};
|
||||
|
||||
//Fsql.Aop.Where = (s, e) => {
|
||||
// if (e.Parameters[0]?.ToString() == "1")
|
||||
// e.IsCancel = true;
|
||||
//};
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IFreeSql Fsql { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IFreeSql>(Fsql);
|
||||
services.AddControllersWithViews();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
Console.OutputEncoding = Encoding.GetEncoding("GB2312");
|
||||
Console.InputEncoding = Encoding.GetEncoding("GB2312");
|
||||
|
||||
app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(a => a.MapControllers());
|
||||
}
|
||||
}
|
||||
}
|
9
Examples/restful/appsettings.Development.json
Normal file
9
Examples/restful/appsettings.Development.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
8
Examples/restful/appsettings.json
Normal file
8
Examples/restful/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
17
Examples/restful/restful.csproj
Normal file
17
Examples/restful/restful.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
0
Examples/restful/xxxtb.db
Normal file
0
Examples/restful/xxxtb.db
Normal file
6
Examples/xamarinFormApp/xamarinForm.Wpf/App.config
Normal file
6
Examples/xamarinFormApp/xamarinForm.Wpf/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
9
Examples/xamarinFormApp/xamarinForm.Wpf/App.xaml
Normal file
9
Examples/xamarinFormApp/xamarinForm.Wpf/App.xaml
Normal file
@ -0,0 +1,9 @@
|
||||
<Application x:Class="xamarinForm.Wpf.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:xamarinForm.Wpf"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
17
Examples/xamarinFormApp/xamarinForm.Wpf/App.xaml.cs
Normal file
17
Examples/xamarinFormApp/xamarinForm.Wpf/App.xaml.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace xamarinForm.Wpf
|
||||
{
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
13
Examples/xamarinFormApp/xamarinForm.Wpf/MainWindow.xaml
Normal file
13
Examples/xamarinFormApp/xamarinForm.Wpf/MainWindow.xaml
Normal file
@ -0,0 +1,13 @@
|
||||
<wpf:FormsApplicationPage x:Class="xamarinForm.Wpf.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:xamarinForm.Wpf"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="450" Width="800"
|
||||
xmlns:wpf="clr-namespace:Xamarin.Forms.Platform.WPF;assembly=Xamarin.Forms.Platform.WPF">
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</wpf:FormsApplicationPage>
|
32
Examples/xamarinFormApp/xamarinForm.Wpf/MainWindow.xaml.cs
Normal file
32
Examples/xamarinFormApp/xamarinForm.Wpf/MainWindow.xaml.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Platform.WPF;
|
||||
|
||||
namespace xamarinForm.Wpf
|
||||
{
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : FormsApplicationPage
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Forms.Init();
|
||||
LoadApplication(new xamarinFormApp.App());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("xamarinForm.Wpf")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("xamarinForm.Wpf")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//若要开始生成可本地化的应用程序,请设置
|
||||
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
|
||||
//例如,如果您在源文件中使用的是美国英语,
|
||||
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
|
||||
//对以下 NeutralResourceLanguage 特性的注释。 更新
|
||||
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
)]
|
||||
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
70
Examples/xamarinFormApp/xamarinForm.Wpf/Properties/Resources.Designer.cs
generated
Normal file
70
Examples/xamarinFormApp/xamarinForm.Wpf/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,70 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本: 4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能导致不正确的行为,如果
|
||||
// 重新生成代码,则所做更改将丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace xamarinForm.Wpf.Properties
|
||||
{
|
||||
/// <summary>
|
||||
/// 强类型资源类,用于查找本地化字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("xamarinForm.Wpf.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
29
Examples/xamarinFormApp/xamarinForm.Wpf/Properties/Settings.Designer.cs
generated
Normal file
29
Examples/xamarinFormApp/xamarinForm.Wpf/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,29 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace xamarinForm.Wpf.Properties
|
||||
{
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
109
Examples/xamarinFormApp/xamarinForm.Wpf/xamarinForm.Wpf.csproj
Normal file
109
Examples/xamarinFormApp/xamarinForm.Wpf/xamarinForm.Wpf.csproj
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{12EC22F5-2586-4AD3-AE03-319C2FAC0B06}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>xamarinForm.Wpf</RootNamespace>
|
||||
<AssemblyName>xamarinForm.Wpf</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Forms.Platform.WPF">
|
||||
<Version>4.8.0.1687</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\xamarinFormApp\xamarinFormApp.csproj">
|
||||
<Project>{e4094717-ed1a-4174-8d86-a65d2ad1380c}</Project>
|
||||
<Name>xamarinFormApp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user