mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-13 06:22:51 +08:00
initial commit
This commit is contained in:
commit
013f35e296
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
[*.cs]
|
||||
|
||||
# Default severity for analyzer diagnostics with category 'Style'
|
||||
dotnet_analyzer_diagnostic.category-Style.severity = none
|
||||
|
||||
# CS0649: 从未对字段“TransactionalAttribute._uowManager”赋值,字段将一直保持其默认值 null
|
||||
dotnet_diagnostic.CS0649.severity = none
|
||||
|
||||
# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
dotnet_diagnostic.CS8618.severity = none
|
||||
|
||||
charset = utf-8-bom
|
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
31
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
name: "Bug Report 🐛"
|
||||
about: 这里只能提交 Bug,提交其他无关信息会被关闭
|
||||
title: ''
|
||||
labels: Bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
以下为必读项,不仔细阅读会导致你的 Issue 被关闭
|
||||
|
||||
1. 该分类下只能提交 Bug,如果要询问使用方法等,请前往讨论区:https://github.com/dotnetcore/FreeSql/discussions
|
||||
2. FreeSql写了许多文档,在提问题前,麻烦先查看[常见问题](https://freesql.net/reference/faq.html)
|
||||
3. 不完整的信息将不会得到任何回复!发布问题后,请保持对 issue 的关注,有时会有需要进一步沟通的信息,很长时间内没有得到答复的 issue 将被关闭。
|
||||
4. 提供可重现的代码,至少应描述以下信息 -->
|
||||
|
||||
#### 问题描述及重现代码:
|
||||
|
||||
```c#
|
||||
// c# code
|
||||
```
|
||||
|
||||
#### 数据库版本
|
||||
|
||||
|
||||
#### 安装的Nuget包
|
||||
|
||||
|
||||
#### .net framework/. net core? 及具体版本
|
||||
|
33
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
name: "Feature Request 🚀"
|
||||
about: 这里只能提交 Feature 请求,提交其他无关信息会被关闭
|
||||
title: ''
|
||||
labels: Feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
以下为必读项,不仔细阅读会导致你的 Issue 被关闭
|
||||
|
||||
1. 该分类下只能提交 Feature,如果要询问使用方法等,请前往讨论区:https://github.com/dotnetcore/FreeSql/discussions
|
||||
2. 请尽量详细的描述清楚你的需求
|
||||
-->
|
||||
|
||||
#### Feature 特性
|
||||
|
||||
```c#
|
||||
// c# code
|
||||
```
|
||||
|
||||
#### 简要描述原因
|
||||
|
||||
```c#
|
||||
// c# code
|
||||
```
|
||||
|
||||
#### 使用场景
|
||||
|
||||
```c#
|
||||
// c# code
|
||||
```
|
41
.github/workflows/docfx.yml
vendored
Normal file
41
.github/workflows/docfx.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
name: Docfx Deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
generate-docs:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
- name: Remove Examples
|
||||
run: dotnet sln FreeSql.sln remove (ls -r Examples/**/*.csproj)
|
||||
- name: Remove FreeSql.Tests
|
||||
run: dotnet sln FreeSql.sln remove (ls -r FreeSql.Tests/**/*.csproj)
|
||||
- name: Install dependencies
|
||||
run: dotnet restore .\FreeSql.sln
|
||||
- name: Build solution
|
||||
run: dotnet build --configuration Release --no-restore .\FreeSql.sln
|
||||
- name: Setup DocFX
|
||||
uses: crazy-max/ghaction-chocolatey@v1
|
||||
with:
|
||||
args: install docfx
|
||||
- name: DocFX Build
|
||||
working-directory: docs
|
||||
run: docfx docfx.json
|
||||
continue-on-error: false
|
||||
- name: Publish
|
||||
if: github.event_name == 'push'
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: docs/_site
|
||||
force_orphan: true
|
17
.github/workflows/gitee-mirror.yml
vendored
Normal file
17
.github/workflows/gitee-mirror.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: Publish
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Sync to Gitee 💕
|
||||
uses: wearerequired/git-mirror-action@master
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
with:
|
||||
source-repo: "git@github.com:dotnetcore/freesql.git"
|
||||
destination-repo: "git@gitee.com:FreeSql/FreeSql-ORM.git"
|
251
.gitignore
vendored
Normal file
251
.gitignore
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
FreeSql.xml
|
||||
FreeSql.DbContext.xml
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
[Xx]64/
|
||||
[Xx]86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
package-lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
|
||||
# TODO: Un-comment the next line if you do not want to checkin
|
||||
# your web deploy settings because they may include unencrypted
|
||||
# passwords
|
||||
#*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Microsoft Azure ApplicationInsights config file
|
||||
ApplicationInsights.config
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
ModelManifest.xml
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
21
Directory.Build.props
Normal file
21
Directory.Build.props
Normal file
@ -0,0 +1,21 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<RepositoryUrl>https://github.com/dotnetcore/FreeSql</RepositoryUrl>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
经常出于版本交叉问题,暂时关闭,在每个项目上设置版本号
|
||||
<PropertyGroup>
|
||||
<Version>3.2.833</Version>
|
||||
</PropertyGroup>
|
||||
-->
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
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>
|
||||
/// 角色表
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public partial class Role : BaseEntity<Role>{
|
||||
/// <summary>
|
||||
/// 角色编号
|
||||
/// </summary>
|
||||
[JsonProperty, Column(IsPrimary = true, IsIdentity = true)]
|
||||
public long RoleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色名称
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string RoleName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 角色描述
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string RoleDesc { get; set; } = string.Empty;
|
||||
|
||||
///// <summary>
|
||||
///// 创建时间
|
||||
///// </summary>
|
||||
//[JsonProperty, Column(DbType = "date")]
|
||||
//public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 启用
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public bool IsEnable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 角色用户多对多导航
|
||||
/// </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>
|
||||
/// 用户角色关系表aa111
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public partial class UserRole : BaseEntity<UserRole>{
|
||||
/// <summary>
|
||||
/// 角色编号1
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public long RoleId { get; set; }
|
||||
/// <summary>
|
||||
/// 角色导航
|
||||
/// </summary>
|
||||
[Navigate("RoleId")]
|
||||
public Role Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户编号
|
||||
/// </summary>
|
||||
[JsonProperty, Column(DbType = "varchar(50)")]
|
||||
public string UserId { get; set; }
|
||||
/// <summary>
|
||||
/// 用户导航
|
||||
/// </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); //同步配置
|
||||
|
||||
//配置单个
|
||||
Fsql.CodeFirst.ApplyConfiguration(new SongConfiguration());
|
||||
|
||||
//批量量配置
|
||||
//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
|
||||
{
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user