mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-14 15:02:50 +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