懒得勤快 7 年之前
父节点
当前提交
583f887e6d
共有 100 个文件被更改,包括 16215 次插入0 次删除
  1. 63 0
      .gitattributes
  2. 267 0
      .gitignore
  3. 40 0
      database/dbo.sql
  4. 1 0
      database/说明.txt
  5. 二进制
      docs/项目文档.docx
  6. 29 0
      src/BLL/App.config
  7. 119 0
      src/BLL/BLL.csproj
  8. 2163 0
      src/BLL/BaseBLL.cs
  9. 50 0
      src/BLL/Blls.cs
  10. 26 0
      src/BLL/Blls.tt
  11. 36 0
      src/BLL/CommentBll.cs
  12. 33 0
      src/BLL/LeaveMessageBll.cs
  13. 20 0
      src/BLL/MenuBll.cs
  14. 29 0
      src/BLL/PostBll.cs
  15. 36 0
      src/BLL/Properties/AssemblyInfo.cs
  16. 146 0
      src/BLL/UserInfoBll.cs
  17. 11 0
      src/BLL/packages.config
  18. 20 0
      src/Common/AggregatedCounter.cs
  19. 30 0
      src/Common/App.config
  20. 175 0
      src/Common/AsposeLicense.cs
  21. 16 0
      src/Common/Assemblies.cs
  22. 109 0
      src/Common/Common.csproj
  23. 482 0
      src/Common/CommonHelper.cs
  24. 142 0
      src/Common/DocumentConvert.cs
  25. 18 0
      src/Common/HangfireHelper.cs
  26. 36 0
      src/Common/Properties/AssemblyInfo.cs
  27. 120 0
      src/Common/RegisterAutomapper.cs
  28. 15 0
      src/Common/packages.config
  29. 25 0
      src/DAL/App.config
  30. 2155 0
      src/DAL/BaseDal.cs
  31. 129 0
      src/DAL/DAL.csproj
  32. 29 0
      src/DAL/Dals.cs
  33. 24 0
      src/DAL/Dals.tt
  34. 36 0
      src/DAL/Properties/AssemblyInfo.cs
  35. 20 0
      src/DAL/packages.config
  36. 44 0
      src/Factory/Factory.cs
  37. 45 0
      src/Factory/Factory.csproj
  38. 81 0
      src/Factory/ObjectPool.cs
  39. 36 0
      src/Factory/Properties/AssemblyInfo.cs
  40. 25 0
      src/IBLL/App.config
  41. 85 0
      src/IBLL/IBLL.csproj
  42. 1643 0
      src/IBLL/IBaseBll.cs
  43. 1615 0
      src/IBLL/IBaseBll.tt
  44. 22 0
      src/IBLL/ICommentBll.cs
  45. 22 0
      src/IBLL/ILeaveMessageBll.cs
  46. 16 0
      src/IBLL/IMenuBll.cs
  47. 25 0
      src/IBLL/IPostBll.cs
  48. 61 0
      src/IBLL/IUserInfoBll.cs
  49. 36 0
      src/IBLL/Properties/AssemblyInfo.cs
  50. 5 0
      src/IBLL/packages.config
  51. 70 0
      src/IBLL/readme.txt
  52. 25 0
      src/IDAL/App.config
  53. 1526 0
      src/IDAL/IBaseDal.cs
  54. 1495 0
      src/IDAL/IBaseDal.tt
  55. 77 0
      src/IDAL/IDAL.csproj
  56. 36 0
      src/IDAL/Properties/AssemblyInfo.cs
  57. 5 0
      src/IDAL/packages.config
  58. 70 0
      src/IDAL/readme.txt
  59. 0 0
      src/Masuit.MyBlogs.WebApp/App_Data/ban.txt
  60. 181 0
      src/Masuit.MyBlogs.WebApp/App_Data/config.json
  61. 1 0
      src/Masuit.MyBlogs.WebApp/App_Data/denyip.txt
  62. 0 0
      src/Masuit.MyBlogs.WebApp/App_Data/mod.txt
  63. 52 0
      src/Masuit.MyBlogs.WebApp/App_Start/AutofacConfig.cs
  64. 65 0
      src/Masuit.MyBlogs.WebApp/App_Start/BundleConfig.cs
  65. 79 0
      src/Masuit.MyBlogs.WebApp/App_Start/CollectRunningInfo.cs
  66. 20 0
      src/Masuit.MyBlogs.WebApp/App_Start/FilterConfig.cs
  67. 141 0
      src/Masuit.MyBlogs.WebApp/App_Start/HangfireConfig.cs
  68. 26 0
      src/Masuit.MyBlogs.WebApp/App_Start/RouteConfig.cs
  69. 25 0
      src/Masuit.MyBlogs.WebApp/App_Start/StartupConfig.cs
  70. 260 0
      src/Masuit.MyBlogs.WebApp/App_Start/SwaggerConfig.cs
  71. 21 0
      src/Masuit.MyBlogs.WebApp/App_Start/WebApiConfig.cs
  72. 40 0
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/anchor/anchor.html
  73. 681 0
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/attachment.css
  74. 60 0
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/attachment.html
  75. 754 0
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/attachment.js
  76. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_chm.gif
  77. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_default.png
  78. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_doc.gif
  79. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_exe.gif
  80. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_jpg.gif
  81. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_mp3.gif
  82. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_mv.gif
  83. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_pdf.gif
  84. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_ppt.gif
  85. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_psd.gif
  86. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_rar.gif
  87. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_txt.gif
  88. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_xls.gif
  89. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/alignicon.gif
  90. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/alignicon.png
  91. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/bg.png
  92. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/file-icons.gif
  93. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/file-icons.png
  94. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/icons.gif
  95. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/icons.png
  96. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/image.png
  97. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/progress.png
  98. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/success.gif
  99. 二进制
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/success.png
  100. 94 0
      src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/background/background.css

+ 63 - 0
.gitattributes

@@ -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

+ 267 - 0
.gitignore

@@ -0,0 +1,267 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# 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/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# 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
+project.fragment.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
+*.VC.VC.opendb
+
+# 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: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# 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/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# 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/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# 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
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+/WebTest
+/ConsoleApp1
+结巴分词
+lucenedir
+/Masuit.MyBlogs.WebApp/upload
+Test

文件差异内容过多而无法显示
+ 40 - 0
database/dbo.sql


+ 1 - 0
database/说明.txt

@@ -0,0 +1 @@
+不建议使用这个数据库,项目运行时会自动创建数据库

二进制
docs/项目文档.docx


+ 29 - 0
src/BLL/App.config

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+    
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
+      <parameters>
+        <parameter value="mssqllocaldb" />
+      </parameters>
+    </defaultConnectionFactory>
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+    </providers>
+  </entityFramework>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-7.0.1.0" newVersion="7.0.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" /></startup></configuration>

+ 119 - 0
src/BLL/BLL.csproj

@@ -0,0 +1,119 @@
+<?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>{F7DEF70A-7EEA-4C03-866B-E351B352711C}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>BLL</RootNamespace>
+    <AssemblyName>BLL</AssemblyName>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <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' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="AngleSharp, Version=0.9.9.0, Culture=neutral, PublicKeyToken=e83494dcdc6d31ea, processorArchitecture=MSIL">
+      <HintPath>..\packages\AngleSharp.0.9.9.2\lib\net45\AngleSharp.dll</HintPath>
+    </Reference>
+    <Reference Include="EFSecondLevelCache, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\EFSecondLevelCache.1.2.0.0\lib\net45\EFSecondLevelCache.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="HtmlSanitizer, Version=3.0.0.0, Culture=neutral, PublicKeyToken=61c49a1a9e79cc28, processorArchitecture=MSIL">
+      <HintPath>..\packages\HtmlSanitizer.4.0.185\lib\net45\HtmlSanitizer.dll</HintPath>
+    </Reference>
+    <Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="StackExchange.Redis, Version=1.2.6.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\StackExchange.Redis.1.2.6\lib\net46\StackExchange.Redis.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.ComponentModel.DataAnnotations" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.IO.Compression" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BaseBLL.cs" />
+    <Compile Include="Blls.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Blls.tt</DependentUpon>
+    </Compile>
+    <Compile Include="CommentBll.cs" />
+    <Compile Include="LeaveMessageBll.cs" />
+    <Compile Include="MenuBll.cs" />
+    <Compile Include="PostBll.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="UserInfoBll.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Masuit.Tools\Masuit.Tools\Masuit.Tools.csproj">
+      <Project>{275d5a0d-c49c-497e-a4b5-f40285c2495f}</Project>
+      <Name>Masuit.Tools</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Common\Common.csproj">
+      <Project>{138F01FA-B23F-4ACA-93DB-D899BB244A1A}</Project>
+      <Name>Common</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Factory\Factory.csproj">
+      <Project>{1363B3D8-457C-4A8C-BAD4-228BC9141A4C}</Project>
+      <Name>Factory</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\IBLL\IBLL.csproj">
+      <Project>{939493b4-a47c-43e2-99e3-92459cd0eb1e}</Project>
+      <Name>IBLL</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\IDAL\IDAL.csproj">
+      <Project>{7997FB01-C9C1-4793-A430-9CA3C3852B37}</Project>
+      <Name>IDAL</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Models\Models.csproj">
+      <Project>{5400CA01-CBCF-4531-A388-3057393D5B4F}</Project>
+      <Name>Models</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Blls.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>Blls.cs</LastGenOutput>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 2163 - 0
src/BLL/BaseBLL.cs

@@ -0,0 +1,2163 @@
+using System;
+using System.Collections.Generic;
+using System.Data.Entity.Infrastructure;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using EFSecondLevelCache;
+using IBLL;
+using IDAL;
+
+namespace BLL
+{
+    /// <summary>
+    /// 业务层基类
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    public class BaseBll<T> : IBaseBll<T> where T : class, new()
+    {
+        public virtual IBaseDal<T> BaseDal { get; set; }// = Factory.CreateInstance<IBaseDal<T>>("DAL." + typeof(T).Name + "Dal");
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAll()
+        {
+            return BaseDal.GetAll();
+        }
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAllNoTracking()
+        {
+            return BaseDal.GetAllNoTracking();
+        }
+
+        /// <summary>
+        /// 从一级缓存获取所有实体
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCache(int timespan = 20)
+        {
+            return BaseDal.GetAllFromCache(timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCacheNoTracking(int timespan = 20)
+        {
+            return BaseDal.GetAllFromCacheNoTracking(timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync(int timespan = 20)
+        {
+            return await BaseDal.GetAllFromCacheNoTrackingAsync(timespan);
+        }
+
+        /// <summary>
+        /// 从一级缓存获取所有实体(异步)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheAsync(int timespan = 20)
+        {
+            return await BaseDal.GetAllFromCacheAsync(timespan);
+        }
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual EFCachedQueryable<T> GetAllFromL2Cache()
+        {
+            return BaseDal.GetAllFromL2Cache();
+        }
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual EFCachedQueryable<T> GetAllFromL2CacheNoTracking()
+        {
+            return BaseDal.GetAllFromL2CacheNoTracking();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAll<TDto>()
+        {
+            return BaseDal.GetAll<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAllNoTracking<TDto>()
+        {
+            return BaseDal.GetAllNoTracking<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCache<TDto>(int timespan = 20) where TDto : class
+        {
+            return BaseDal.GetAllFromCache<TDto>(timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheAsync<TDto>(int timespan = 20) where TDto : class
+        {
+            return await BaseDal.GetAllFromCacheAsync<TDto>(timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCacheNoTracking<TDto>(int timespan = 20) where TDto : class
+        {
+            return BaseDal.GetAllFromCacheNoTracking<TDto>(timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TDto>(int timespan = 20) where TDto : class
+        {
+            return await BaseDal.GetAllFromCacheNoTrackingAsync<TDto>(timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2Cache<TDto>()
+        {
+            return BaseDal.GetAllFromL2Cache<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2CacheNoTracking<TDto>()
+        {
+            return BaseDal.GetAllFromL2CacheNoTracking<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAll<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetAll(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAllNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetAllNoTracking(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return BaseDal.GetAllFromCache(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return await BaseDal.GetAllFromCacheAsync(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return BaseDal.GetAllFromCacheNoTracking(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return await BaseDal.GetAllFromCacheNoTrackingAsync(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromL2Cache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetAllFromL2Cache(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromL2CacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetAllFromL2CacheNoTracking(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAll<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetAll<TS, TDto>(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAllNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetAllNoTracking<TS, TDto>(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return BaseDal.GetAllFromCache<TS, TDto>(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return await BaseDal.GetAllFromCacheAsync<TS, TDto>(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return BaseDal.GetAllFromCacheNoTracking<TS, TDto>(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return await BaseDal.GetAllFromCacheNoTrackingAsync<TS, TDto>(orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2Cache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
+        {
+            return BaseDal.GetAllFromL2Cache<TS, TDto>(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
+        {
+            return BaseDal.GetAllFromL2CacheNoTracking<TS, TDto>(orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadEntities(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntities(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadEntities<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntities(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadEntities<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntities<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        /// <returns></returns>
+        public virtual IQueryable<TDto> LoadEntities<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntities<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCache(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return BaseDal.LoadEntitiesFromCache(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns></returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return BaseDal.LoadEntitiesFromCache(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return BaseDal.LoadEntitiesFromCache<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return BaseDal.LoadEntitiesFromCache<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2Cache(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntitiesFromL2Cache(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntitiesFromL2Cache(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2Cache<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntitiesFromL2Cache<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntitiesFromL2Cache<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<T>> LoadEntitiesAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesAsync(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IOrderedQueryable<T>> LoadEntitiesAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return await BaseDal.LoadEntitiesFromCacheAsync(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return await BaseDal.LoadEntitiesFromCacheAsync(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.LoadEntitiesFromCacheAsync<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.LoadEntitiesFromCacheAsync<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheAsync(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadEntitiesNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntitiesNoTracking(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IOrderedQueryable<T> LoadEntitiesNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntitiesNoTracking(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadEntitiesNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntitiesNoTracking<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadEntitiesNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntitiesNoTracking<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return BaseDal.LoadEntitiesFromCacheNoTracking(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return BaseDal.LoadEntitiesFromCacheNoTracking(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return BaseDal.LoadEntitiesFromCacheNoTracking<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return BaseDal.LoadEntitiesFromCacheNoTracking<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2CacheNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntitiesFromL2CacheNoTracking(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntitiesFromL2CacheNoTracking(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.LoadEntitiesFromL2CacheNoTracking<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadEntitiesFromL2CacheNoTracking<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IQueryable<T>> LoadEntitiesNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesNoTrackingAsync(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<T>> LoadEntitiesNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesNoTrackingAsync(@where, @orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesNoTrackingAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesNoTrackingAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return await BaseDal.LoadEntitiesFromCacheNoTrackingAsync(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return await BaseDal.LoadEntitiesFromCacheNoTrackingAsync(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.LoadEntitiesFromCacheNoTrackingAsync<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheNoTrackingAsync(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheNoTrackingAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntity(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntity(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntity<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntity(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntity<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntity<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntity<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntity<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromCache(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return BaseDal.GetFirstEntityFromCache(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual T GetFirstEntityFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return BaseDal.GetFirstEntityFromCache(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return BaseDal.GetFirstEntityFromCache<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return BaseDal.GetFirstEntityFromCache<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromL2Cache(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntityFromL2Cache(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual T GetFirstEntityFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntityFromL2Cache(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromL2Cache<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntityFromL2Cache<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntityFromL2Cache<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return await BaseDal.GetFirstEntityFromCacheAsync(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return await BaseDal.GetFirstEntityFromCacheAsync(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.GetFirstEntityFromCacheAsync<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.GetFirstEntityFromCacheAsync<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheAsync(where);
+        }
+
+        /// <summary>
+        ///  获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityAsync(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntityNoTracking(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntityNoTracking(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntityNoTracking<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntityNoTracking<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return BaseDal.GetFirstEntityFromCacheNoTracking(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return BaseDal.GetFirstEntityFromCacheNoTracking(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return BaseDal.GetFirstEntityFromCacheNoTracking<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return BaseDal.GetFirstEntityFromCacheNoTracking<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromL2CacheNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntityFromL2CacheNoTracking(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntityFromL2CacheNoTracking(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.GetFirstEntityFromL2CacheNoTracking<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.GetFirstEntityFromL2CacheNoTracking<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityNoTrackingAsync(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityNoTrackingAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityNoTrackingAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityNoTrackingAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return await BaseDal.GetFirstEntityFromCacheNoTrackingAsync(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return await BaseDal.GetFirstEntityFromCacheNoTrackingAsync(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.GetFirstEntityFromCacheNoTrackingAsync<TDto>(where, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return await BaseDal.GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheNoTrackingAsync(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheNoTrackingAsync(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await BaseDal.GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 根据ID找实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        public virtual T GetById(object id)
+        {
+            return BaseDal.GetById(id);
+        }
+
+        /// <summary>
+        /// 根据ID找实体(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetByIdAsync(object id)
+        {
+            return await BaseDal.GetByIdAsync(id);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby,
+            bool isAsc = true)
+        {
+            return BaseDal.LoadPageEntities(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadPageEntities<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
+        {
+            return BaseDal.LoadPageEntities<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return BaseDal.LoadPageEntitiesFromCache(pageIndex, pageSize, out totalCount, where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc, int timespan = 30) where TDto : class
+        {
+            return BaseDal.LoadPageEntitiesFromCache<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromL2Cache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadPageEntitiesFromL2Cache(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromL2Cache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
+        {
+            return BaseDal.LoadPageEntitiesFromL2Cache<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadPageEntitiesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadPageEntitiesNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadPageEntitiesNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadPageEntitiesNoTracking<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromCacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return BaseDal.LoadPageEntitiesFromCacheNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromCacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return BaseDal.LoadPageEntitiesFromCacheNoTracking<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc, timespan);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadPageEntitiesFromL2CacheNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return BaseDal.LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+        }
+
+        /// <summary>
+        /// 根据ID删除实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteById(object id)
+        {
+            return BaseDal.DeleteById(id);
+        }
+
+        /// <summary>
+        /// 根据ID删除实体并保存
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteByIdSaved(object id)
+        {
+            BaseDal.DeleteById(id);
+            return SaveChanges() > 0;
+        }
+
+        /// <summary>
+        /// 根据ID删除实体并保存(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        public virtual async Task<int> DeleteByIdSavedAsync(object id)
+        {
+            BaseDal.DeleteById(id);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 删除实体并保存
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteEntity(T t)
+        {
+            return BaseDal.DeleteEntity(t);
+        }
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        public virtual int DeleteEntity(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.DeleteEntity(where);
+        }
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        public virtual int DeleteEntitySaved(Expression<Func<T, bool>> @where)
+        {
+            BaseDal.DeleteEntity(where);
+            return SaveChanges();
+        }
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        public virtual async Task<int> DeleteEntitySavedAsync(Expression<Func<T, bool>> @where)
+        {
+            BaseDal.DeleteEntity(where);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 根据条件删除实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        public virtual async Task<int> DeleteEntityAsync(Expression<Func<T, bool>> @where)
+        {
+            return await BaseDal.DeleteEntityAsync(where);
+        }
+
+        /// <summary>
+        /// 删除实体并保存
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteEntitySaved(T t)
+        {
+            BaseDal.DeleteEntity(t);
+            return SaveChanges() > 0;
+        }
+
+        /// <summary>
+        /// 删除实体并保存(异步)
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        public virtual async Task<int> DeleteEntitySavedAsync(T t)
+        {
+            BaseDal.DeleteEntity(t);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 更新实体
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual bool UpdateEntity(T t)
+        {
+            return BaseDal.UpdateEntity(t);
+        }
+
+        /// <summary>
+        /// 更新实体并保存
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual bool UpdateEntitySaved(T t)
+        {
+            BaseDal.UpdateEntity(t);
+            return SaveChanges() > 0;
+        }
+
+        /// <summary>
+        /// 更新实体并保存(异步)
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual async Task<int> UpdateEntitySavedAsync(T t)
+        {
+            BaseDal.UpdateEntity(t);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 根据条件更新实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual int UpdateEntity(Expression<Func<T, bool>> @where, T t)
+        {
+            return BaseDal.UpdateEntity(where, t);
+        }
+
+        /// <summary>
+        /// 根据条件更新实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual async Task<int> UpdateEntityAsync(Expression<Func<T, bool>> @where, T t)
+        {
+            return await BaseDal.UpdateEntityAsync(where, t);
+        }
+
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        public virtual T AddEntity(T t)
+        {
+            return BaseDal.AddEntity(t);
+        }
+
+        /// <summary>
+        /// 添加实体并保存
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        public virtual T AddEntitySaved(T t)
+        {
+            T entity = BaseDal.AddEntity(t);
+            bool b = SaveChanges() > 0;
+            return b ? entity : null;
+        }
+
+        /// <summary>
+        /// 添加实体并保存(异步)
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        public virtual async Task<int> AddEntitySavedAsync(T t)
+        {
+            BaseDal.AddEntity(t);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 添加或更新
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        public virtual void AddOrUpdate(Expression<Func<T, object>> exp, params T[] entities)
+        {
+            BaseDal.AddOrUpdate(exp, entities);
+        }
+
+        /// <summary>
+        /// 添加或更新并保存
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        public virtual int AddOrUpdateSaved(Expression<Func<T, object>> exp, params T[] entities)
+        {
+            AddOrUpdate(exp, entities);
+            return SaveChanges();
+        }
+
+        /// <summary>
+        /// 添加或更新并保存(异步)
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        public virtual async Task<int> AddOrUpdateSavedAsync(Expression<Func<T, object>> exp, params T[] entities)
+        {
+            AddOrUpdate(exp, entities);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 统一保存的方法
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        public virtual int SaveChanges()
+        {
+            return BaseDal.SaveChanges();
+        }
+
+        /// <summary>
+        /// 统一保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        public virtual async Task<int> SaveChangesAsync()
+        {
+            return await BaseDal.SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 判断实体是否在数据库中存在
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>是否存在</returns>
+        public virtual bool Any(Expression<Func<T, bool>> @where)
+        {
+            return BaseDal.Any(where);
+        }
+
+        /// <summary>
+        /// 删除多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteEntities(IEnumerable<T> list)
+        {
+            return BaseDal.DeleteEntities(list);
+        }
+
+        /// <summary>
+        /// 删除多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteEntitiesSaved(IEnumerable<T> list)
+        {
+            BaseDal.DeleteEntities(list);
+            return SaveChanges() > 0;
+        }
+
+        /// <summary>
+        /// 删除多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        public virtual async Task<int> DeleteEntitiesSavedAsync(IEnumerable<T> list)
+        {
+            BaseDal.DeleteEntities(list);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 更新多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        public virtual bool UpdateEntities(IEnumerable<T> list)
+        {
+            return BaseDal.UpdateEntities(list);
+        }
+
+        /// <summary>
+        /// 更新多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        public virtual bool UpdateEntitiesSaved(IEnumerable<T> list)
+        {
+            BaseDal.UpdateEntities(list);
+            return SaveChanges() > 0;
+        }
+
+        /// <summary>
+        /// 更新多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        public virtual async Task<int> UpdateEntitiesSavedAsync(IEnumerable<T> list)
+        {
+            BaseDal.UpdateEntities(list);
+            return await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 添加多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        public virtual IEnumerable<T> AddEntities(IList<T> list)
+        {
+            IEnumerable<T> entities = BaseDal.AddEntities(list);
+            SaveChanges();
+            return entities;
+        }
+
+        /// <summary>
+        /// 添加多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        public virtual async Task<IEnumerable<T>> AddEntitiesAsync(IList<T> list)
+        {
+            IEnumerable<T> entities = BaseDal.AddEntities(list);
+            await SaveChangesAsync();
+            return entities;
+        }
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        /// <returns>泛型集合</returns>
+        public virtual DbRawSqlQuery<TS> SqlQuery<TS>(string sql, params SqlParameter[] parameters)
+        {
+            return BaseDal.SqlQuery<TS>(sql, parameters);
+        }
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        public virtual DbRawSqlQuery SqlQuery(Type t, string sql, params SqlParameter[] parameters)
+        {
+            return BaseDal.SqlQuery(t, sql, parameters);
+        }
+
+        /// <summary>
+        /// 执行DML语句
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="parameters"></param>
+        public virtual void ExecuteSql(string sql, params SqlParameter[] parameters)
+        {
+            BaseDal.ExecuteSql(sql, parameters);
+        }
+
+        /// <summary>
+        /// 批量添加实体
+        /// </summary>
+        /// <param name="list">需要添加的实体</param>
+        public virtual void BulkInsert(IEnumerable<T> list)
+        {
+            BaseDal.BulkInsert(list);
+        }
+
+        /// <summary>
+        /// 统一批量保存数据
+        /// </summary>
+        public virtual void BulkSaveChanges()
+        {
+            BaseDal.BulkSaveChanges();
+        }
+    }
+}

+ 50 - 0
src/BLL/Blls.cs

@@ -0,0 +1,50 @@
+
+using IBLL;
+using Models.Entity;
+namespace BLL
+{
+	
+	public partial class BroadcastBll :BaseBll<Broadcast>,IBroadcastBll{}   
+	
+	public partial class CategoryBll :BaseBll<Category>,ICategoryBll{}   
+	
+	public partial class CommentBll :BaseBll<Comment>,ICommentBll{}   
+	
+	public partial class ContactsBll :BaseBll<Contacts>,IContactsBll{}   
+	
+	public partial class DonateBll :BaseBll<Donate>,IDonateBll{}   
+	
+	public partial class InternalMessageBll :BaseBll<InternalMessage>,IInternalMessageBll{}   
+	
+	public partial class InterviewBll :BaseBll<Interview>,IInterviewBll{}   
+	
+	public partial class InterviewDetailBll :BaseBll<InterviewDetail>,IInterviewDetailBll{}   
+	
+	public partial class IssueBll :BaseBll<Issue>,IIssueBll{}   
+	
+	public partial class LeaveMessageBll :BaseBll<LeaveMessage>,ILeaveMessageBll{}   
+	
+	public partial class LinksBll :BaseBll<Links>,ILinksBll{}   
+	
+	public partial class LoginRecordBll :BaseBll<LoginRecord>,ILoginRecordBll{}   
+	
+	public partial class MenuBll :BaseBll<Menu>,IMenuBll{}   
+	
+	public partial class MiscBll :BaseBll<Misc>,IMiscBll{}   
+	
+	public partial class NoticeBll :BaseBll<Notice>,INoticeBll{}   
+	
+	public partial class PostBll :BaseBll<Post>,IPostBll{}   
+	
+	public partial class PostAccessRecordBll :BaseBll<PostAccessRecord>,IPostAccessRecordBll{}   
+	
+	public partial class PostHistoryVersionBll :BaseBll<PostHistoryVersion>,IPostHistoryVersionBll{}   
+	
+	public partial class SearchDetailsBll :BaseBll<SearchDetails>,ISearchDetailsBll{}   
+	
+	public partial class SeminarBll :BaseBll<Seminar>,ISeminarBll{}   
+	
+	public partial class SystemSettingBll :BaseBll<SystemSetting>,ISystemSettingBll{}   
+	
+	public partial class UserInfoBll :BaseBll<UserInfo>,IUserInfoBll{}   
+}

+ 26 - 0
src/BLL/Blls.tt

@@ -0,0 +1,26 @@
+<#@ template language="C#" debug="false" hostspecific="true"#>
+<#@ include file="EF.Utility.CS.ttinclude"#>
+<#@output extension=".cs"#>
+<#
+CodeGenerationTools code = new CodeGenerationTools(this);
+MetadataLoader loader = new MetadataLoader(this);
+CodeRegion region = new CodeRegion(this, 1);
+MetadataTools ef = new MetadataTools(this);
+
+string inputFile = @"..\\ModelCodeGenerate\\Model.edmx";//EF模型路径
+
+EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
+string namespaceName = code.VsNamespaceSuggestion();
+EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
+#>
+using IBLL;
+using Models.Entity;
+namespace BLL
+{
+<#
+foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
+{
+#>	
+	public partial class <#=entity.Name#>Bll :BaseBll<<#=entity.Name#>>,I<#=entity.Name#>Bll{}   
+<#}#>
+}

+ 36 - 0
src/BLL/CommentBll.cs

@@ -0,0 +1,36 @@
+using System.Data.Entity.Infrastructure;
+using System.Linq;
+using Masuit.Tools.Net;
+using Models.Application;
+using Models.Entity;
+
+namespace BLL
+{
+    public partial class CommentBll
+    {
+        /// <summary>
+        /// 通过存储过程获得自己以及自己所有的子元素集合
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public DbRawSqlQuery<Comment> GetSelfAndAllChildrenCommentsByParentId(int id)
+        {
+            return WebExtension.GetDbContext<DataContext>().Database.SqlQuery<Comment>("exec sp_getChildrenCommentByParentId " + id);
+        }
+
+        /// <summary>
+        /// 根据无级子级找顶级父级评论id
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public int GetParentCommentIdByChildId(int id)
+        {
+            DbRawSqlQuery<int> raw = WebExtension.GetDbContext<DataContext>().Database.SqlQuery<int>("exec sp_getParentCommentIdByChildId " + id);
+            if (raw.Any())
+            {
+                return raw.FirstOrDefault();
+            }
+            return 0;
+        }
+    }
+}

+ 33 - 0
src/BLL/LeaveMessageBll.cs

@@ -0,0 +1,33 @@
+using System.Data.Entity.Infrastructure;
+using System.Linq;
+using Masuit.Tools.Net;
+using Models.Application;
+using Models.Entity;
+
+namespace BLL
+{
+    public partial class LeaveMessageBll
+    {
+        /// <summary>
+        /// 通过存储过程获得自己以及自己所有的子元素集合
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public DbRawSqlQuery<LeaveMessage> GetSelfAndAllChildrenMessagesByParentId(int id) => WebExtension.GetDbContext<DataContext>().Database.SqlQuery<LeaveMessage>("exec sp_getChildrenLeaveMsgByParentId " + id);
+
+        /// <summary>
+        /// 根据无级子级找顶级父级留言id
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public int GetParentMessageIdByChildId(int id)
+        {
+            var raw = WebExtension.GetDbContext<DataContext>().Database.SqlQuery<int>("exec sp_getParentMessageIdByChildId " + id);
+            if (raw.Any())
+            {
+                return raw.FirstOrDefault();
+            }
+            return 0;
+        }
+    }
+}

+ 20 - 0
src/BLL/MenuBll.cs

@@ -0,0 +1,20 @@
+using System.Data.Entity.Infrastructure;
+using Masuit.Tools.Net;
+using Models.Application;
+using Models.Entity;
+
+namespace BLL
+{
+    public partial class MenuBll
+    {
+        /// <summary>
+        /// 通过存储过程获得自己以及自己所有的子元素集合
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public DbRawSqlQuery<Menu> GetChildrenMenusByParentId(int id)
+        {
+            return WebExtension.GetDbContext<DataContext>().Database.SqlQuery<Menu>("exec sp_getChildrenMenusByParentId " + id);
+        }
+    }
+}

+ 29 - 0
src/BLL/PostBll.cs

@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+using System.Linq;
+using Models.DTO;
+using Models.Entity;
+using Models.Enum;
+
+namespace BLL
+{
+    public partial class PostBll
+    {
+        public bool MoveToCategory(int pid, int cid)
+        {
+            Post post = GetById(pid);
+            post.CategoryId = cid;
+            return UpdateEntitySaved(post);
+        }
+    }
+    public partial class MenuBll
+    {
+        /// <summary>
+        /// 获取菜单
+        /// </summary>
+        /// <returns></returns>
+        public IList<MenuOutputDto> GetMenus()
+        {
+            return BaseDal.LoadEntitiesFromCacheNoTracking<MenuOutputDto>(m => m.Status == Status.Available).ToList();
+        }
+    }
+}

+ 36 - 0
src/BLL/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("BLL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BLL")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("f7def70a-7eea-4c03-866b-e351b352711c")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 146 - 0
src/BLL/UserInfoBll.cs

@@ -0,0 +1,146 @@
+using System;
+using Common;
+using Masuit.Tools.DateTimeExt;
+using Masuit.Tools.Security;
+using Masuit.Tools.Win32;
+using Models.DTO;
+using Models.Entity;
+
+namespace BLL
+{
+    public partial class UserInfoBll
+    {
+        /// <summary>
+        /// 根据用户名获取
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public UserInfo GetByUsername(string name)
+        {
+            return GetFirstEntity(u => u.Username.Equals(name));
+        }
+
+        /// <summary>
+        /// 登录
+        /// </summary>
+        /// <param name="username"></param>
+        /// <param name="password"></param>
+        /// <returns></returns>
+        public UserInfoOutputDto Login(string username, string password)
+        {
+            UserInfo userInfo = GetByUsername(username);
+            if (userInfo != null)
+            {
+                UserInfoOutputDto user = userInfo.Mapper<UserInfoOutputDto>();
+                string key = userInfo.SaltKey;
+                string pwd = userInfo.Password;
+                password = password.MDString3(key);
+                if (pwd.Equals(password))
+                {
+                    return user;
+                }
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// 注册
+        /// </summary>
+        /// <param name="userInfo"></param>
+        /// <returns></returns>
+        public UserInfo Register(UserInfo userInfo)
+        {
+            UserInfo exist = GetFirstEntity(u => u.Username.Equals(userInfo.Username) || u.Email.Equals(userInfo.Email));
+            if (exist is null)
+            {
+                var salt = $"{new Random().StrictNext()}{DateTime.Now.GetTotalMilliseconds()}".MDString2(Guid.NewGuid().ToString()).AESEncrypt();
+                userInfo.Password = userInfo.Password.MDString3(salt);
+                userInfo.SaltKey = salt;
+                UserInfo added = AddEntity(userInfo);
+                int line = SaveChanges();
+                return line > 0 ? added : null;
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// 检查用户名是否存在
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public bool UsernameExist(string name)
+        {
+            UserInfo userInfo = GetByUsername(name);
+            return userInfo != null;
+        }
+
+        /// <summary>
+        /// 检查邮箱是否存在
+        /// </summary>
+        /// <param name="email"></param>
+        /// <returns></returns>
+        public bool EmailExist(string email) => GetFirstEntityNoTracking(u => u.Email.Equals(email)) != null;
+
+        /// <summary>
+        /// 修改密码
+        /// </summary>
+        /// <param name="name">用户名,邮箱或者电话号码</param>
+        /// <param name="oldPwd">旧密码</param>
+        /// <param name="newPwd">新密码</param>
+        /// <returns></returns>
+        public bool ChangePassword(string name, string oldPwd, string newPwd)
+        {
+            UserInfo userInfo = GetByUsername(name);
+            if (userInfo != null)
+            {
+                string key = userInfo.SaltKey;
+                string pwd = userInfo.Password;
+                oldPwd = oldPwd.MDString3(key);
+                if (pwd.Equals(oldPwd))
+                {
+                    var salt = $"{new Random().StrictNext()}{DateTime.Now.GetTotalMilliseconds()}".MDString2(Guid.NewGuid().ToString()).AESEncrypt();
+                    userInfo.Password = newPwd.MDString3(salt);
+                    userInfo.SaltKey = salt;
+                    return SaveChanges() > 0;
+                }
+            }
+            return false;
+        }
+
+        public bool ChangePassword(int id, string oldPwd, string newPwd)
+        {
+            UserInfo userInfo = GetById(id);
+            if (userInfo != null)
+            {
+                string key = userInfo.SaltKey;
+                string pwd = userInfo.Password;
+                oldPwd = oldPwd.MDString3(key);
+                if (pwd.Equals(oldPwd))
+                {
+                    var salt = $"{new Random().StrictNext()}{DateTime.Now.GetTotalMilliseconds()}".MDString2(Guid.NewGuid().ToString()).AESEncrypt();
+                    userInfo.Password = newPwd.MDString3(salt);
+                    userInfo.SaltKey = salt;
+                    return SaveChanges() > 0;
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 重置密码
+        /// </summary>
+        /// <returns></returns>
+        public bool ResetPassword(string name, string newPwd = "123456")
+        {
+            UserInfo userInfo = GetByUsername(name);
+            if (userInfo != null)
+            {
+                var salt = $"{new Random().StrictNext()}{DateTime.Now.GetTotalMilliseconds()}".MDString2(Guid.NewGuid().ToString()).AESEncrypt();
+                userInfo.Password = newPwd.MDString3(salt);
+                userInfo.SaltKey = salt;
+                return SaveChanges() > 0;
+            }
+            return false;
+        }
+    }
+}

+ 11 - 0
src/BLL/packages.config

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="AngleSharp" version="0.9.9.2" targetFramework="net46" />
+  <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
+  <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
+  <package id="EntityFramework.zh-Hans" version="6.2.0" targetFramework="net45" />
+  <package id="HtmlSanitizer" version="4.0.185" targetFramework="net46" />
+  <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net46" />
+  <package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
+  <package id="StackExchange.Redis" version="1.2.6" targetFramework="net46" />
+</packages>

+ 20 - 0
src/Common/AggregatedCounter.cs

@@ -0,0 +1,20 @@
+using Models.ViewModel;
+
+namespace Common
+{
+    /// <summary>
+    /// 访客统计缓存
+    /// </summary>
+    public class AggregatedCounter
+    {
+        /// <summary>
+        /// 独立访客统计汇总
+        /// </summary>
+        public static AnalysisModel UniqueInterviews { get; set; } = new AnalysisModel();
+
+        /// <summary>
+        /// 直接访客统计汇总
+        /// </summary>
+        public static AnalysisModel TotalInterviews { get; set; } = new AnalysisModel();
+    }
+}

+ 30 - 0
src/Common/App.config

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+    
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
+      <parameters>
+        <parameter value="mssqllocaldb" />
+      </parameters>
+    </defaultConnectionFactory>
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+    </providers>
+  </entityFramework>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" /></startup>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-7.0.1.0" newVersion="7.0.1.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>

+ 175 - 0
src/Common/AsposeLicense.cs

@@ -0,0 +1,175 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Xml;
+
+namespace Common
+{
+    /// <summary>
+    /// Aspose内存补丁
+    /// </summary>
+    public static class AsposeLicense
+    {
+        private static readonly string AsposeList = "Aspose.3D.dll, Aspose.BarCode.dll, Aspose.BarCode.Compact.dll, Aspose.BarCode.WPF.dll, Aspose.Cells.GridDesktop.dll, Aspose.Cells.GridWeb.dll, Aspose.CAD.dll, Aspose.Cells.dll, Aspose.Diagram.dll, Aspose.Email.dll, Aspose.Imaging.dll, Aspose.Note.dll, Aspose.OCR.dll, Aspose.Pdf.dll, Aspose.Slides.dll, Aspose.Tasks.dll, Aspose.Words.dll";
+
+        /// <summary>
+        /// 启动Aspose的内存破解
+        /// </summary>
+        public static void ActivateMemoryPatching()
+        {
+            Assembly[] arr = AppDomain.CurrentDomain.GetAssemblies();
+            foreach (Assembly assembly in arr)
+            {
+                if (AsposeList.IndexOf(assembly.FullName.Split(',')[0] + ".dll") != -1)
+                    ActivateForAssembly(assembly);
+            }
+            AppDomain.CurrentDomain.AssemblyLoad += ActivateOnLoad;
+        }
+
+        private static void ActivateOnLoad(object sender, AssemblyLoadEventArgs e)
+        {
+            if (AsposeList.IndexOf(e.LoadedAssembly.FullName.Split(',')[0] + ".dll") != -1)
+                ActivateForAssembly(e.LoadedAssembly);
+        }
+
+        private static void ActivateForAssembly(Assembly assembly)
+        {
+            MethodInfo miLicensed1 = typeof(AsposeLicense).GetMethod("InvokeMe1", BindingFlags.NonPublic | BindingFlags.Static);
+            MethodInfo miLicensed2 = typeof(AsposeLicense).GetMethod("InvokeMe2", BindingFlags.NonPublic | BindingFlags.Static);
+
+            Dictionary<string, MethodInfo> miDict = new Dictionary<string, MethodInfo>
+            {
+                ["System.DateTime"] = miLicensed1,
+                ["System.Xml.XmlElement"] = miLicensed2
+            };
+
+            Type[] arrType = null;
+            bool isFound = false;
+            int nCount = 0;
+
+            try
+            {
+                arrType = assembly.GetTypes();
+            }
+            catch (ReflectionTypeLoadException err)
+            {
+                arrType = err.Types;
+            }
+            foreach (Type type in arrType)
+            {
+                if (isFound) break;
+                if (type == null) continue;
+                MethodInfo[] arrMInfo = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static);
+                foreach (MethodInfo info in arrMInfo)
+                {
+                    if (isFound) break;
+                    try
+                    {
+                        string strMethod = info.ToString();
+                        if ((strMethod.IndexOf("(System.Xml.XmlElement, System.String)") > 0) && miDict.ContainsKey(info.ReturnType.ToString()))
+                        {
+                            var miEvaluation = info;
+                            MemoryPatching(miEvaluation, miDict[miEvaluation.ReturnType.ToString()]);
+                            nCount++;
+                            if (((assembly.FullName.IndexOf("Aspose.Pdf") == -1) && (nCount == 2)) || ((assembly.FullName.IndexOf("Aspose.Pdf") != -1) && (nCount == 6)))
+                            {
+                                isFound = true;
+                                break;
+                            }
+                        }
+                    }
+                    catch
+                    {
+                        throw new InvalidOperationException("MemoryPatching for \"" + assembly.FullName + "\" failed !");
+                    }
+                }
+            }
+
+            string[] aParts = assembly.FullName.Split(',');
+            string fName = aParts[0];
+            if (fName.IndexOf("Aspose.BarCode.") != -1)
+                fName = "Aspose.BarCode";
+            else if (fName.IndexOf("Aspose.3D") != -1)
+                fName = "Aspose.ThreeD";
+
+            try
+            {
+                Type type2 = assembly.GetType(fName + ".License");
+                MethodInfo mi = type2.GetMethod("SetLicense", new[] { typeof(Stream) });
+                const string LData = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPExpY2Vuc2U+CiAgPERhdGE+CiAgICA8TGljZW5zZWRUbz5MaWNlbnNlZTwvTGljZW5zZWRUbz4KICAgIDxFbWFpbFRvPmxpY2Vuc2VlQGVtYWlsLmNvbTwvRW1haWxUbz4KICAgIDxMaWNlbnNlVHlwZT5EZXZlbG9wZXIgT0VNPC9MaWNlbnNlVHlwZT4KICAgIDxMaWNlbnNlTm90ZT5MaW1pdGVkIHRvIDEwMDAgZGV2ZWxvcGVyLCB1bmxpbWl0ZWQgcGh5c2ljYWwgbG9jYXRpb25zPC9MaWNlbnNlTm90ZT4KICAgIDxPcmRlcklEPjc4NDM3ODU3Nzg1PC9PcmRlcklEPgogICAgPFVzZXJJRD4xMTk3ODkyNDM3OTwvVXNlcklEPgogICAgPE9FTT5UaGlzIGlzIGEgcmVkaXN0cmlidXRhYmxlIGxpY2Vuc2U8L09FTT4KICAgIDxQcm9kdWN0cz4KICAgICAgPFByb2R1Y3Q+QXNwb3NlLlRvdGFsIFByb2R1Y3QgRmFtaWx5PC9Qcm9kdWN0PgogICAgPC9Qcm9kdWN0cz4KICAgIDxFZGl0aW9uVHlwZT5FbnRlcnByaXNlPC9FZGl0aW9uVHlwZT4KICAgIDxTZXJpYWxOdW1iZXI+e0YyQjk3MDQ1LTFCMjktNEIzRi1CRDUzLTYwMUVGRkExNUFBOX08L1NlcmlhbE51bWJlcj4KICAgIDxTdWJzY3JpcHRpb25FeHBpcnk+MjA5OTEyMzE8L1N1YnNjcmlwdGlvbkV4cGlyeT4KICAgIDxMaWNlbnNlVmVyc2lvbj4zLjA8L0xpY2Vuc2VWZXJzaW9uPgogIDwvRGF0YT4KICA8U2lnbmF0dXJlPlFYTndiM05sTGxSdmRHRnNJRkJ5YjJSMVkzUWdSbUZ0YVd4NTwvU2lnbmF0dXJlPgo8L0xpY2Vuc2U+";
+                Stream stream = new MemoryStream(Convert.FromBase64String(LData));
+                stream.Seek(0, SeekOrigin.Begin);
+                mi.Invoke(Activator.CreateInstance(type2, null), new[] { stream });
+            }
+            catch
+            {
+                throw new InvalidOperationException("SetLicense for \"" + assembly.FullName + "\" failed !");
+            }
+        }
+
+        private static DateTime InvokeMe1(XmlElement element, string name)
+        {
+            return DateTime.MaxValue;
+        }
+
+        private static XmlElement InvokeMe2(XmlElement element, string name)
+        {
+            if (element.LocalName == "License")
+            {
+                const string License64 = "PERhdGE+PExpY2Vuc2VkVG8+R3JvdXBEb2NzPC9MaWNlbnNlZFRvPjxMaWNlbnNlVHlwZT5TaXRlIE9FTTwvTGljZW5zZVR5cGU+PExpY2Vuc2VOb3RlPkxpbWl0ZWQgdG8gMTAgZGV2ZWxvcGVyczwvTGljZW5zZU5vdGU+PE9yZGVySUQ+MTMwNzI0MDQwODQ5PC9PcmRlcklEPjxPRU0+VGhpcyBpcyBhIHJlZGlzdHJpYnV0YWJsZSBsaWNlbnNlPC9PRU0+PFByb2R1Y3RzPjxQcm9kdWN0PkFzcG9zZS5Ub3RhbDwvUHJvZHVjdD48L1Byb2R1Y3RzPjxFZGl0aW9uVHlwZT5FbnRlcnByaXNlPC9FZGl0aW9uVHlwZT48U2VyaWFsTnVtYmVyPjliNTc5NTAxLTUyNjEtNDIyMC04NjcwLWZjMmQ4Y2NkZDkwYzwvU2VyaWFsTnVtYmVyPjxTdWJzY3JpcHRpb25FeHBpcnk+MjAxNDA3MjQ8L1N1YnNjcmlwdGlvbkV4cGlyeT48TGljZW5zZVZlcnNpb24+Mi4yPC9MaWNlbnNlVmVyc2lvbj48L0RhdGE+PFNpZ25hdHVyZT5udFpocmRoL3I0QS81ZFpsU2dWYnhac0hYSFBxSjZ5UVVYa0RvaW4vS2lVZWhUUWZET0lQdHdzUlR2NmRTUVplOVdXekNnV3RGdkdROWpmR2QySmF4YUQvbkx1ZEk2R0VVajhqeVhUMG4vbWRrMEF1WVZNYlBXRjJYd3dSTnFlTmRrblYyQjhrZVFwbDJ2RzZVbnhxS2J6VVFxS2Rhc1pzZ2w1Q0xqSFVEWms9PC9TaWduYXR1cmU+";
+                element.InnerXml = new UTF8Encoding().GetString(Convert.FromBase64String(License64));
+            }
+
+            if (element.LocalName == "BlackList")
+            {
+                const string BlackList64 = "PERhdGE+PC9EYXRhPjxTaWduYXR1cmU+cUJwMEx1cEVoM1ZnOWJjeS8vbUVXUk9KRWZmczRlY25iTHQxYlNhanU2NjY5RHlad09FakJ1eEdBdVBxS1hyd0x5bmZ5VWplYUNGQ0QxSkh2RVUxVUl5eXJOTnBSMXc2NXJIOUFyUCtFbE1lVCtIQkZ4NFMzckFVMnd6dkxPZnhGeU9DQ0dGQ2UraTdiSHlGQk44WHp6R1UwdGRPMGR1RTFoRTQ5M1RNY3pRPTwvU2lnbmF0dXJlPg==";
+                element.InnerXml = new UTF8Encoding().GetString(Convert.FromBase64String(BlackList64));
+            }
+
+            XmlNodeList elementsByTagName = element.GetElementsByTagName(name);
+            if (elementsByTagName.Count <= 0)
+                return null;
+
+            return (XmlElement)elementsByTagName[0];
+        }
+
+        private static unsafe void MemoryPatching(MethodBase miEvaluation, MethodBase miLicensed)
+        {
+            IntPtr intPtrEval = GetMemoryAddress(miEvaluation);
+            IntPtr intPtrLicensed = GetMemoryAddress(miLicensed);
+
+            if (IntPtr.Size == 8)
+                *(long*)intPtrEval.ToPointer() = *(long*)intPtrLicensed.ToPointer();
+            else
+                *(int*)intPtrEval.ToPointer() = *(int*)intPtrLicensed.ToPointer();
+        }
+
+        private static unsafe IntPtr GetMemoryAddress(MethodBase mb)
+        {
+            RuntimeHelpers.PrepareMethod(mb.MethodHandle);
+
+            if ((Environment.Version.Major >= 4) || ((Environment.Version.Major == 2) && (Environment.Version.MinorRevision >= 3053)))
+                return new IntPtr((int*)mb.MethodHandle.Value.ToPointer() + 2);
+
+            ulong* location = (ulong*)mb.MethodHandle.Value.ToPointer();
+            int index = (int)((*location >> 32) & 0xFF);
+            if (IntPtr.Size == 8)
+            {
+                ulong* classStart = (ulong*)mb.DeclaringType.TypeHandle.Value.ToPointer();
+                ulong* address = classStart + index + 10;
+                return new IntPtr(address);
+            }
+            else
+            {
+                uint* classStart = (uint*)mb.DeclaringType.TypeHandle.Value.ToPointer();
+                uint* address = classStart + index + 10;
+                return new IntPtr(address);
+            }
+        }
+    }
+}
+
+//End

+ 16 - 0
src/Common/Assemblies.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+
+namespace Common
+{
+    /// <summary>
+    /// 程序集缓存
+    /// </summary>
+    public static class Assemblies
+    {
+        public static Assembly ServiceAssembly { get; set; } = Assembly.LoadFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", ConfigurationManager.AppSettings["BllPath"] ?? "BLL.dll"));
+        public static Assembly RepositoryAssembly { get; set; } = Assembly.LoadFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", ConfigurationManager.AppSettings["DalPath"] ?? "DAL.dll"));
+    }
+}

+ 109 - 0
src/Common/Common.csproj

@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{138F01FA-B23F-4ACA-93DB-D899BB244A1A}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Common</RootNamespace>
+    <AssemblyName>Common</AssemblyName>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Aspose.Words, Version=17.7.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\libs\Aspose.Words.dll</HintPath>
+    </Reference>
+    <Reference Include="AutoMapper, Version=7.0.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
+      <HintPath>..\packages\AutoMapper.7.0.1\lib\net45\AutoMapper.dll</HintPath>
+    </Reference>
+    <Reference Include="EFSecondLevelCache, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\EFSecondLevelCache.1.2.0.0\lib\net45\EFSecondLevelCache.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="Hangfire.Core, Version=1.6.19.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\Hangfire.Core.1.6.19\lib\net45\Hangfire.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Hangfire.SqlServer, Version=1.6.19.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\Hangfire.SqlServer.1.6.19\lib\net45\Hangfire.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="Microsoft.Owin, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Owin.4.0.0\lib\net451\Microsoft.Owin.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.4.0.0\lib\net451\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
+      <HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
+    </Reference>
+    <Reference Include="StackExchange.Redis, Version=1.2.6.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\StackExchange.Redis.1.2.6\lib\net46\StackExchange.Redis.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.IO.Compression" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AggregatedCounter.cs" />
+    <Compile Include="AsposeLicense.cs" />
+    <Compile Include="Assemblies.cs" />
+    <Compile Include="CommonHelper.cs" />
+    <Compile Include="DocumentConvert.cs" />
+    <Compile Include="HangfireHelper.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RegisterAutomapper.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Masuit.Tools\Masuit.Tools\Masuit.Tools.csproj">
+      <Project>{275d5a0d-c49c-497e-a4b5-f40285c2495f}</Project>
+      <Name>Masuit.Tools</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Models\Models.csproj">
+      <Project>{5400CA01-CBCF-4531-A388-3057393D5B4F}</Project>
+      <Name>Models</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 482 - 0
src/Common/CommonHelper.cs

@@ -0,0 +1,482 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text.RegularExpressions;
+using EFSecondLevelCache;
+using Hangfire;
+using Masuit.Tools;
+using Masuit.Tools.Media;
+#if !DEBUG
+using Masuit.Tools.Models;
+#endif
+using Masuit.Tools.Net;
+using Masuit.Tools.NoSQL;
+using Models.Application;
+using Newtonsoft.Json.Linq;
+
+namespace Common
+{
+    /// <summary>
+    /// 公共类库
+    /// </summary>
+    public static class CommonHelper
+    {
+        /// <summary>
+        /// 敏感词
+        /// </summary>
+        public static string BanRegex { get; set; } = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "ban.txt"));
+
+        /// <summary>
+        /// 审核词
+        /// </summary>
+        public static string ModRegex { get; set; } = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "mod.txt"));
+
+        /// <summary>
+        /// 禁止IP
+        /// </summary>
+        public static string DenyIP { get; set; } = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "denyip.txt"));
+
+        /// <summary>
+        /// 每IP错误的次数统计
+        /// </summary>
+        public static ConcurrentDictionary<string, int> IPErrorTimes { get; set; } = new ConcurrentDictionary<string, int>();
+
+        /// <summary>
+        /// 访问量
+        /// </summary>
+        public static long InterviewCount { get; set; } = WebExtension.GetDbContext<DataContext>().Interview.Count();
+
+        /// <summary>
+        /// 网站运营开始时间
+        /// </summary>
+        public static DateTime RunningStart { get; set; } = WebExtension.GetDbContext<DataContext>().Interview.Min(i => i.ViewTime);
+
+        /// <summary>
+        /// 网站启动时间
+        /// </summary>
+        public static DateTime StartupTime { get; set; } = DateTime.Now;
+
+        /// <summary>
+        /// 在线人数
+        /// </summary>
+        public static int OnlineCount
+        {
+            get
+            {
+                try
+                {
+                    using (var redisHelper = RedisHelper.GetInstance(1))
+                    {
+                        return redisHelper.GetServer().Keys(1, "Session:*").Count();
+                    }
+                }
+                catch
+                {
+                    return 1;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 类型映射
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static T Mapper<T>(this object source) where T : class => AutoMapper.Mapper.Map<T>(source);
+
+        /// <summary>
+        /// 获取设置参数
+        /// </summary>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public static string GetSettings(string key)
+        {
+            using (var db = new DataContext())
+            {
+                return db.SystemSetting.Where(s => s.Name.Equals(key)).Cacheable().FirstOrDefault()?.Value;
+            }
+        }
+
+        #region 性能历史数据
+
+        public static List<object[]> HistoryCpuLoad { get; set; } = new List<object[]>();
+        public static List<object[]> HistoryMemoryUsage { get; set; } = new List<object[]>();
+        public static List<object[]> HistoryCpuTemp { get; set; } = new List<object[]>();
+        public static List<object[]> HistoryIORead { get; set; } = new List<object[]>();
+        public static List<object[]> HistoryIOWrite { get; set; } = new List<object[]>();
+        public static List<object[]> HistoryNetSend { get; set; } = new List<object[]>();
+        public static List<object[]> HistoryNetReceive { get; set; } = new List<object[]>();
+
+        #endregion
+
+        /// <summary>
+        /// 发送邮件
+        /// </summary>
+        /// <param name="title">标题</param>
+        /// <param name="content">内容</param>
+        /// <param name="tos">收件人</param>
+        public static void SendMail(string title, string content, string tos)
+        {
+#if !DEBUG
+            new Email()
+            {
+                EnableSsl = true,
+                Body = content,
+                SmtpServer = GetSettings("smtp"),
+                Username = GetSettings("EmailFrom"),
+                Password = GetSettings("EmailPwd"),
+                SmtpPort = GetSettings("SmtpPort").ToInt32(),
+                Subject = title,
+                Tos = tos
+            }.Send();
+#endif
+        }
+
+        /// <summary>
+        /// 上传图片到新浪图床
+        /// </summary>
+        /// <param name="file">文件名</param>
+        /// <returns></returns>
+        public static (string, bool) UploadImage(string file)
+        {
+            string ext = Path.GetExtension(file);
+            if (new FileInfo(file).Length > 5 * 1024 * 1024)
+            {
+                if (ext.Equals(".jpg", StringComparison.InvariantCultureIgnoreCase))
+                {
+                    using (FileStream stream = File.OpenRead(file))
+                    {
+                        string newfile = Path.Combine(Environment.GetEnvironmentVariable("temp"), "".CreateShortToken(16) + ext);
+                        using (FileStream fs = new FileStream(newfile, FileMode.OpenOrCreate, FileAccess.ReadWrite))
+                        {
+                            ImageUtilities.CompressImage(stream, fs, 100, 5120);
+                            return UploadImage(newfile);
+                        }
+                    }
+                }
+
+                return ("", false);
+            }
+
+            string[] apis = { "https://zs.mtkan.cc/upload.php", "https://tu.zsczys.com/upload.php", "https://api.yum6.cn/sinaimg.php?type=multipart", "http://180.165.190.225:672/v1/upload" };
+            int index = 0;
+            string url = String.Empty;
+            bool success = false;
+            for (int i = 0; i < 30; i++)
+            {
+                using (HttpClient httpClient = new HttpClient())
+                {
+                    httpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+                    using (var stream = File.OpenRead(file))
+                    {
+                        using (var bc = new StreamContent(stream))
+                        {
+                            bc.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "1" + ext, Name = "file" };
+                            using (var content = new MultipartFormDataContent { bc })
+                            {
+                                var code = httpClient.PostAsync(apis[index], content).ContinueWith(t =>
+                                {
+                                    if (t.IsCanceled || t.IsFaulted)
+                                    {
+                                        //Console.WriteLine("发送请求出错了" + t.Exception.Message);
+                                        t.Exception.InnerExceptions.ForEach(e => { Console.WriteLine("发送请求出错了:" + e); });
+                                        return 0;
+                                    }
+
+                                    var res = t.Result;
+                                    if (res.IsSuccessStatusCode)
+                                    {
+                                        string s = res.Content.ReadAsStringAsync().Result;
+                                        var token = JObject.Parse(s);
+                                        switch (index)
+                                        {
+                                            case 0:
+                                            case 1:
+                                                s = (string)token["original_pic"];
+                                                if (!s.Contains("Array.jpg"))
+                                                {
+                                                    url = s;
+                                                    return 1;
+                                                }
+
+                                                return 2;
+                                            case 2:
+                                                s = (string)token["code"];
+                                                if (s.Equals("200"))
+                                                {
+                                                    url = (string)token["url"];
+                                                    return 1;
+                                                }
+
+                                                return 2;
+                                            case 3:
+                                                try
+                                                {
+                                                    url = "https://wx2.sinaimg.cn/large/" + token["wbpid"] + "." + token["type"];
+                                                    return 1;
+                                                }
+                                                catch
+                                                {
+                                                    return 2;
+                                                }
+                                        }
+                                    }
+
+                                    return 2;
+                                }).Result;
+                                if (code == 1)
+                                {
+                                    success = true;
+                                    break;
+                                }
+
+                                if (code == 0)
+                                {
+                                    if (i % 10 == 9)
+                                    {
+                                        index++;
+                                        if (index == apis.Length)
+                                        {
+                                            Console.WriteLine("所有上传接口都挂掉了,重试sm.ms图床");
+                                            return UploadImageFallback(file);
+                                        }
+
+                                        Console.WriteLine("正在准备重试图片上传接口:" + apis[index]);
+                                        continue;
+                                    }
+                                }
+
+                                if (code == 2)
+                                {
+                                    index++;
+                                    if (index == apis.Length)
+                                    {
+                                        Console.WriteLine("所有上传接口都挂掉了,重试sm.ms图床");
+                                        return UploadImageFallback(file);
+                                    }
+
+                                    Console.WriteLine("正在准备重试图片上传接口:" + apis[index]);
+                                    continue;
+                                }
+
+                                Console.WriteLine("准备重试上传图片");
+                            }
+                        }
+                    }
+                }
+            }
+
+            return (url.Replace("/thumb150/", "/large/"), success);
+        }
+
+        /// <summary>
+        /// 上传图片到sm图床
+        /// </summary>
+        /// <param name="file">文件名</param>
+        /// <returns></returns>
+        private static (string, bool) UploadImageFallback(string file)
+        {
+            string url = String.Empty;
+            bool success = false;
+            string ext = Path.GetExtension(file);
+            for (int i = 0; i < 10; i++)
+            {
+                using (HttpClient httpClient = new HttpClient())
+                {
+                    httpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+                    using (var stream = File.OpenRead(file))
+                    {
+                        using (var bc = new StreamContent(stream))
+                        {
+                            bc.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "".CreateShortToken() + ext, Name = "smfile" };
+                            using (var content = new MultipartFormDataContent { bc })
+                            {
+                                var code = httpClient.PostAsync("https://sm.ms/api/upload?inajax=1&ssl=1", content).ContinueWith(t =>
+                                {
+                                    if (t.IsCanceled || t.IsFaulted)
+                                    {
+                                        //Console.WriteLine("发送请求出错了" + t.Exception);
+                                        t.Exception.InnerExceptions.ForEach(e => { Console.WriteLine("发送请求出错了:" + e); });
+                                        return 0;
+                                    }
+
+                                    var res = t.Result;
+                                    if (res.IsSuccessStatusCode)
+                                    {
+                                        string s = res.Content.ReadAsStringAsync().Result;
+                                        var token = JObject.Parse(s);
+                                        url = (string)token["data"]["url"];
+                                        return 1;
+                                    }
+
+                                    return 2;
+                                }).Result;
+                                if (code == 1)
+                                {
+                                    success = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (success)
+            {
+                return (url, success);
+            }
+
+            return UploadImageFallback2(file);
+        }
+
+        /// <summary>
+        /// 上传图片到百度图床
+        /// </summary>
+        /// <param name="file">文件名</param>
+        /// <returns></returns>
+        private static (string, bool) UploadImageFallback2(string file)
+        {
+            string url = String.Empty;
+            bool success = false;
+            string ext = Path.GetExtension(file);
+            for (int i = 0; i < 10; i++)
+            {
+                using (HttpClient httpClient = new HttpClient())
+                {
+                    httpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+                    using (var stream = File.OpenRead(file))
+                    {
+                        using (var bc = new StreamContent(stream))
+                        {
+                            bc.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "".CreateShortToken() + ext, Name = "uploaded_file[]" };
+                            using (var content = new MultipartFormDataContent { bc })
+                            {
+                                var code = httpClient.PostAsync("https://upload.cc/image_upload", content).ContinueWith(t =>
+                                {
+                                    if (t.IsCanceled || t.IsFaulted)
+                                    {
+                                        //Console.WriteLine("发送请求出错了" + t.Exception);
+                                        t.Exception.InnerExceptions.ForEach(e => { Console.WriteLine("发送请求出错了:" + e); });
+                                        return 0;
+                                    }
+
+                                    var res = t.Result;
+                                    if (res.IsSuccessStatusCode)
+                                    {
+                                        string s = res.Content.ReadAsStringAsync().Result;
+                                        var token = JObject.Parse(s);
+                                        if ((int)token["code"] == 100)
+                                        {
+                                            url = "https://upload.cc/" + (string)token["success_image"][0]["url"];
+                                            return 1;
+                                        }
+                                    }
+
+                                    return 2;
+                                }).Result;
+                                if (code == 1)
+                                {
+                                    success = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (success)
+            {
+                return (url, success);
+            }
+
+            return UploadImageFallback3(file);
+        }
+
+        /// <summary>
+        /// 上传图片到百度图床
+        /// </summary>
+        /// <param name="file">文件名</param>
+        /// <returns></returns>
+        private static (string, bool) UploadImageFallback3(string file)
+        {
+            string url = String.Empty;
+            bool success = false;
+            string ext = Path.GetExtension(file);
+            for (int i = 0; i < 10; i++)
+            {
+                using (HttpClient httpClient = new HttpClient())
+                {
+                    httpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+                    using (var stream = File.OpenRead(file))
+                    {
+                        using (var bc = new StreamContent(stream))
+                        {
+                            bc.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "".CreateShortToken() + ext, Name = "img" };
+                            using (var content = new MultipartFormDataContent { bc })
+                            {
+                                var code = httpClient.PostAsync("http://upload.otar.im/api/upload/imgur", content).ContinueWith(t =>
+                                {
+                                    if (t.IsCanceled || t.IsFaulted)
+                                    {
+                                        //Console.WriteLine("发送请求出错了" + t.Exception);
+                                        t.Exception.InnerExceptions.ForEach(e => { Console.WriteLine("发送请求出错了:" + e); });
+                                        return 0;
+                                    }
+
+                                    var res = t.Result;
+                                    if (res.IsSuccessStatusCode)
+                                    {
+                                        string s = res.Content.ReadAsStringAsync().Result;
+                                        var token = JObject.Parse(s);
+                                        url = (string)token["url"];
+                                        return 1;
+                                    }
+
+                                    return 2;
+                                }).Result;
+                                if (code == 1)
+                                {
+                                    success = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            return (url, success);
+        }
+
+        public static string ReplaceImgSrc(string content)
+        {
+            var mc = Regex.Matches(content, "<img.+?src=\"(.+?)\".+?>", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
+            foreach (Match m in mc)
+            {
+                var src = m.Groups[1].Value;
+                if (src.StartsWith("/"))
+                {
+                    var path = Path.Combine(AppContext.BaseDirectory, src.Replace("/", @"\").Substring(1));
+                    if (File.Exists(path))
+                    {
+                        var (url, success) = UploadImage(path);
+                        if (success)
+                        {
+                            content = content.Replace(src, url);
+                            BackgroundJob.Enqueue(() => File.Delete(path));
+                        }
+                    }
+                }
+            }
+
+            return content;
+        }
+    }
+}

+ 142 - 0
src/Common/DocumentConvert.cs

@@ -0,0 +1,142 @@
+using System.IO;
+using System.Threading.Tasks;
+using Aspose.Words;
+
+namespace Common
+{
+    /// <summary>
+    /// 文档转换操作
+    /// </summary>
+    public static class DocumentConvert
+    {
+        static DocumentConvert()
+        {
+            // AsposeLicense.ActivateMemoryPatching();
+        }
+
+        #region doc转html
+
+        /// <summary>
+        /// doc转html
+        /// </summary>
+        /// <param name="docPath">doc文件路径</param>
+        /// <param name="htmlDir">生成的html所在目录,由于生成html后会将图片都放到同级的目录下,所以用文件夹保存,默认的html文件名为index.html</param>
+        /// <param name="index">默认文档名为index.html</param>
+        public static void Doc2Html(string docPath, string htmlDir, string index = "index.html")
+        {
+            Document doc = new Document(docPath);
+            doc.Save(Path.Combine(htmlDir, index), SaveFormat.Html);
+        }
+
+        /// <summary>
+        /// doc转html
+        /// </summary>
+        /// <param name="docPath">doc文件路径</param>
+        /// <param name="htmlDir">生成的html所在目录,由于生成html后会将图片都放到同级的目录下,所以用文件夹保存,默认的html文件名为index.html</param>
+        /// <param name="index">默认文档名为index.html</param>
+        public static void Doc2HtmlAsync(string docPath, string htmlDir, string index = "index.html")
+        {
+            Document doc = new Document(docPath);
+            Task.Run(() => doc.Save(Path.Combine(htmlDir, index), SaveFormat.Html));
+        }
+
+        #endregion
+
+        #region doc转pdf
+
+        /// <summary>
+        /// doc转pdf
+        /// </summary>
+        /// <param name="docPath">doc源文件</param>
+        /// <param name="pdfPath">目标pdf文件</param>
+        /// <param name="paperSize">纸张大小</param>
+        /// <param name="leftMargin">左边距</param>
+        /// <param name="rightMargin">右边距</param>
+        /// <param name="topMargin">上边距</param>
+        /// <param name="bottomMargin">下边距</param>
+        public static void Doc2Pdf(string docPath, string pdfPath, PaperSize paperSize = PaperSize.A4, double leftMargin = 20, double rightMargin = 20, double topMargin = 20, double bottomMargin = 20)
+        {
+            Document doc = new Document(docPath);
+            PageSetup pageSetup = new DocumentBuilder(doc).PageSetup;
+            pageSetup.PaperSize = paperSize;
+            pageSetup.LeftMargin = leftMargin;
+            pageSetup.RightMargin = rightMargin;
+            pageSetup.TopMargin = topMargin;
+            pageSetup.BottomMargin = bottomMargin;
+            doc.Save(pdfPath, SaveFormat.Pdf);
+        }
+
+        /// <summary>
+        /// doc转pdf
+        /// </summary>
+        /// <param name="docPath">doc源文件</param>
+        /// <param name="pdfPath">目标pdf文件</param>
+        /// <param name="paperSize">纸张大小</param>
+        /// <param name="leftMargin">左边距</param>
+        /// <param name="rightMargin">右边距</param>
+        /// <param name="topMargin">上边距</param>
+        /// <param name="bottomMargin">下边距</param>
+        public static void Doc2PdfAsync(string docPath, string pdfPath, PaperSize paperSize = PaperSize.A4, double leftMargin = 20, double rightMargin = 20, double topMargin = 20, double bottomMargin = 20)
+        {
+            Document doc = new Document(docPath);
+            PageSetup pageSetup = new DocumentBuilder(doc).PageSetup;
+            pageSetup.PaperSize = paperSize;
+            pageSetup.LeftMargin = leftMargin;
+            pageSetup.RightMargin = rightMargin;
+            pageSetup.TopMargin = topMargin;
+            pageSetup.BottomMargin = bottomMargin;
+            Task.Run(() => doc.Save(pdfPath, SaveFormat.Pdf));
+        }
+
+        #endregion
+
+        #region html转Word
+
+        /// <summary>
+        /// html转Word
+        /// </summary>
+        /// <param name="htmlPath">html源文件</param>
+        /// <param name="docPath">目标doc文件</param>
+        /// <param name="paperSize">纸张大小,默认A4纸</param>
+        /// <param name="leftMargin">左边距,默认10</param>
+        /// <param name="rightMargin">右边距,默认10</param>
+        /// <param name="topMargin">上边距,默认10</param>
+        /// <param name="bottomMargin">下边距,默认10</param>
+        public static void Html2Word(string htmlPath, string docPath, PaperSize paperSize = PaperSize.A4, double leftMargin = 20, double rightMargin = 20, double topMargin = 20, double bottomMargin = 20)
+        {
+            Document doc = new Document(htmlPath);
+            PageSetup pageSetup = new DocumentBuilder(doc).PageSetup;
+            pageSetup.PaperSize = paperSize;
+            pageSetup.LeftMargin = leftMargin;
+            pageSetup.RightMargin = rightMargin;
+            pageSetup.TopMargin = topMargin;
+            pageSetup.BottomMargin = bottomMargin;
+            doc.Save(docPath, SaveFormat.Doc);
+        }
+
+        /// <summary>
+        /// html转Word
+        /// </summary>
+        /// <param name="htmlPath">html源文件</param>
+        /// <param name="docPath">目标doc文件</param>
+        /// <param name="paperSize">纸张大小,默认A4纸</param>
+        /// <param name="leftMargin">左边距,默认10</param>
+        /// <param name="rightMargin">右边距,默认10</param>
+        /// <param name="topMargin">上边距,默认10</param>
+        /// <param name="bottomMargin">下边距,默认10</param>
+        public static void Html2WordAsync(string htmlPath, string docPath, PaperSize paperSize = PaperSize.A4, double leftMargin = 20, double rightMargin = 20, double topMargin = 20, double bottomMargin = 20)
+        {
+            Document doc = new Document(htmlPath);
+            PageSetup pageSetup = new DocumentBuilder(doc).PageSetup;
+            pageSetup.PaperSize = paperSize;
+            pageSetup.LeftMargin = leftMargin;
+            pageSetup.RightMargin = rightMargin;
+            pageSetup.TopMargin = topMargin;
+            pageSetup.BottomMargin = bottomMargin;
+            Task.Run(() => doc.Save(docPath, SaveFormat.Doc));
+        }
+
+        #endregion
+
+    }
+}

+ 18 - 0
src/Common/HangfireHelper.cs

@@ -0,0 +1,18 @@
+using System;
+using Hangfire;
+using Hangfire.Common;
+using Hangfire.States;
+
+namespace Common
+{
+    public static class HangfireHelper
+    {
+        private static BackgroundJobClient Client { get; set; } = new BackgroundJobClient();
+
+        public static string CreateJob(Type type, string method, string queue = "", params dynamic[] args)
+        {
+            var job = new Job(type, type.GetMethod(method), args);
+            return string.IsNullOrEmpty(queue) ? Client.Create(job, new EnqueuedState()) : Client.Create(job, new EnqueuedState(queue));
+        }
+    }
+}

+ 36 - 0
src/Common/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Common")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Common")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("138f01fa-b23f-4aca-93db-d899bb244a1a")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 120 - 0
src/Common/RegisterAutomapper.cs

@@ -0,0 +1,120 @@
+using System.Linq;
+using AutoMapper;
+using Models.DTO;
+using Models.Entity;
+using Models.ViewModel;
+
+namespace Common
+{
+    public static class RegisterAutomapper
+    {
+        public static void Excute()
+        {
+            Mapper.Initialize(m =>
+            {
+                m.CreateMap<Broadcast, BroadcastInputDto>();
+                m.CreateMap<BroadcastInputDto, Broadcast>();
+                m.CreateMap<Broadcast, BroadcastOutputDto>();
+                m.CreateMap<BroadcastOutputDto, Broadcast>();
+                m.CreateMap<BroadcastOutputDto, BroadcastInputDto>();
+                m.CreateMap<BroadcastInputDto, BroadcastOutputDto>();
+
+                m.CreateMap<Category, CategoryInputDto>();
+                m.CreateMap<CategoryInputDto, Category>();
+                m.CreateMap<Category, CategoryOutputDto>();
+                m.CreateMap<CategoryOutputDto, Category>();
+                m.CreateMap<CategoryInputDto, CategoryOutputDto>();
+                m.CreateMap<CategoryOutputDto, CategoryInputDto>();
+
+                m.CreateMap<Comment, CommentInputDto>();
+                m.CreateMap<CommentInputDto, Comment>();
+                m.CreateMap<Comment, CommentOutputDto>();
+                m.CreateMap<CommentOutputDto, Comment>();
+                m.CreateMap<CommentInputDto, CommentOutputDto>();
+                m.CreateMap<CommentOutputDto, CommentInputDto>();
+                m.CreateMap<Comment, CommentViewModel>().ForMember(c => c.CommentDate, e => e.MapFrom(c => c.CommentDate.ToString("yyyy-MM-dd HH:mm:ss")));
+
+                m.CreateMap<Contacts, ContactsInputDto>();
+                m.CreateMap<ContactsInputDto, Contacts>();
+                m.CreateMap<Contacts, ContactsOutputDto>();
+                m.CreateMap<ContactsOutputDto, Contacts>();
+                m.CreateMap<ContactsInputDto, ContactsOutputDto>();
+                m.CreateMap<ContactsOutputDto, ContactsInputDto>();
+
+                m.CreateMap<Interview, InterviewOutputDto>();
+
+                m.CreateMap<LeaveMessage, LeaveMessageInputDto>();
+                m.CreateMap<LeaveMessageInputDto, LeaveMessage>();
+                m.CreateMap<LeaveMessage, LeaveMessageOutputDto>();
+                m.CreateMap<LeaveMessageOutputDto, LeaveMessage>();
+                m.CreateMap<LeaveMessageInputDto, LeaveMessageOutputDto>();
+                m.CreateMap<LeaveMessageOutputDto, LeaveMessageInputDto>();
+                m.CreateMap<LeaveMessage, LeaveMessageViewModel>().ForMember(l => l.PostDate, e => e.MapFrom(l => l.PostDate.ToString("yyyy-MM-dd HH:mm:ss")));
+
+                m.CreateMap<Links, LinksInputDto>();
+                m.CreateMap<LinksInputDto, Links>();
+                m.CreateMap<Links, LinksOutputDto>();
+                m.CreateMap<LinksOutputDto, Links>();
+                m.CreateMap<LinksInputDto, LinksOutputDto>();
+                m.CreateMap<LinksOutputDto, LinksInputDto>();
+
+                m.CreateMap<Menu, MenuInputDto>();
+                m.CreateMap<MenuInputDto, Menu>();
+                m.CreateMap<Menu, MenuOutputDto>();
+                m.CreateMap<MenuOutputDto, Menu>();
+                m.CreateMap<MenuInputDto, MenuOutputDto>();
+                m.CreateMap<MenuOutputDto, MenuInputDto>();
+
+                m.CreateMap<Misc, MiscInputDto>();
+                m.CreateMap<MiscInputDto, Misc>();
+                m.CreateMap<Misc, MiscOutputDto>();
+                m.CreateMap<MiscOutputDto, Misc>();
+                m.CreateMap<MiscInputDto, MiscOutputDto>();
+                m.CreateMap<MiscOutputDto, MiscInputDto>();
+                m.CreateMap<Misc, MiscViewModel>().ForMember(c => c.PostDate, e => e.MapFrom(c => c.PostDate.ToString("yyyy-MM-dd HH:mm:ss"))).ForMember(c => c.ModifyDate, e => e.MapFrom(c => c.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")));
+
+                m.CreateMap<Notice, NoticeInputDto>();
+                m.CreateMap<NoticeInputDto, Notice>();
+                m.CreateMap<Notice, NoticeOutputDto>();
+                m.CreateMap<NoticeOutputDto, Notice>();
+                m.CreateMap<NoticeInputDto, NoticeOutputDto>();
+                m.CreateMap<NoticeOutputDto, NoticeInputDto>();
+                m.CreateMap<Notice, NoticeViewModel>().ForMember(c => c.PostDate, e => e.MapFrom(c => c.PostDate.ToString("yyyy-MM-dd HH:mm:ss"))).ForMember(c => c.ModifyDate, e => e.MapFrom(c => c.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")));
+
+                m.CreateMap<Post, PostInputDto>();
+                m.CreateMap<Post, PostHistoryVersion>().ForMember(v => v.PostId, e => e.MapFrom(p => p.Id));
+                m.CreateMap<PostInputDto, Post>();
+                m.CreateMap<Post, PostOutputDto>().ForMember(p => p.CategoryName, e => e.MapFrom(p => p.Category.Name)).ForMember(p => p.ViewCount, e => e.MapFrom(p => p.PostAccessRecord.Any() ? p.PostAccessRecord.Sum(r => r.ClickCount) : 1));
+                m.CreateMap<PostOutputDto, Post>();
+                m.CreateMap<PostInputDto, PostOutputDto>();
+                m.CreateMap<PostHistoryVersion, PostOutputDto>().ForMember(p => p.CategoryName, e => e.MapFrom(p => p.Category.Name));
+                m.CreateMap<PostOutputDto, PostInputDto>();
+                m.CreateMap<Post, PostViewModel>().ForMember(p => p.CategoryName, e => e.MapFrom(p => p.Category.Name)).ForMember(p => p.PostDate, e => e.MapFrom(p => p.PostDate.ToString("yyyy-MM-dd HH:mm:ss"))).ForMember(p => p.ModifyDate, e => e.MapFrom(p => p.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")));
+
+                m.CreateMap<SearchDetails, SearchDetailsInputDto>();
+                m.CreateMap<SearchDetailsInputDto, SearchDetails>();
+                m.CreateMap<SearchDetails, SearchDetailsOutputDto>();
+                m.CreateMap<SearchDetailsOutputDto, SearchDetails>();
+                m.CreateMap<SearchDetailsInputDto, SearchDetailsOutputDto>();
+                m.CreateMap<SearchDetailsOutputDto, SearchDetailsInputDto>();
+
+                m.CreateMap<UserInfo, UserInfoInputDto>();
+                m.CreateMap<UserInfoInputDto, UserInfo>();
+                m.CreateMap<UserInfo, UserInfoOutputDto>();
+                m.CreateMap<UserInfoOutputDto, UserInfo>();
+                m.CreateMap<UserInfoInputDto, UserInfoOutputDto>();
+                m.CreateMap<UserInfoOutputDto, UserInfoInputDto>();
+
+                m.CreateMap<LoginRecord, LoginRecordOutputDto>();
+                m.CreateMap<LoginRecordOutputDto, LoginRecord>();
+
+                m.CreateMap<Seminar, SeminarInputDto>();
+                m.CreateMap<SeminarInputDto, Seminar>();
+                m.CreateMap<Seminar, SeminarOutputDto>();
+                m.CreateMap<SeminarOutputDto, Seminar>();
+                m.CreateMap<SeminarInputDto, SeminarOutputDto>();
+                m.CreateMap<SeminarOutputDto, SeminarInputDto>();
+            });
+        }
+    }
+}

+ 15 - 0
src/Common/packages.config

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="AutoMapper" version="7.0.1" targetFramework="net46" />
+  <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
+  <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
+  <package id="Hangfire" version="1.6.19" targetFramework="net46" />
+  <package id="Hangfire.Core" version="1.6.19" targetFramework="net46" />
+  <package id="Hangfire.SqlServer" version="1.6.19" targetFramework="net46" />
+  <package id="Microsoft.Owin" version="4.0.0" targetFramework="net46" />
+  <package id="Microsoft.Owin.Host.SystemWeb" version="4.0.0" targetFramework="net46" />
+  <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net46" />
+  <package id="Owin" version="1.0" targetFramework="net45" />
+  <package id="StackExchange.Redis" version="1.2.6" targetFramework="net46" />
+  <package id="System.ValueTuple" version="4.5.0" targetFramework="net46" />
+</packages>

+ 25 - 0
src/DAL/App.config

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+    
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
+      <parameters>
+        <parameter value="mssqllocaldb" />
+      </parameters>
+    </defaultConnectionFactory>
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+    </providers>
+  </entityFramework>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-7.0.1.0" newVersion="7.0.1.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>

+ 2155 - 0
src/DAL/BaseDal.cs

@@ -0,0 +1,2155 @@
+using System;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
+using System.Data.Entity.Migrations;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using AutoMapper;
+using EFSecondLevelCache;
+using EntityFramework.Caching;
+using EntityFramework.Extensions;
+using IDAL;
+using Masuit.Tools;
+using Masuit.Tools.Net;
+using Masuit.Tools.Systems;
+using Models.Application;
+
+namespace DAL
+{
+    /// <summary>
+    /// DAL基类
+    /// </summary>
+    /// <typeparam name="T">实体类型</typeparam>
+    public class BaseDal<T> : Disposable, IBaseDal<T> where T : class, new()
+    {
+        public virtual DataContext DataContext { get; set; } = WebExtension.GetDbContext<DataContext>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAll()
+        {
+            return DataContext.Set<T>();
+        }
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAllNoTracking()
+        {
+            return DataContext.Set<T>().AsNoTracking();
+        }
+
+        /// <summary>
+        /// 从一级缓存获取所有实体
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCache(int timespan = 20)
+        {
+            return DataContext.Set<T>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCacheNoTracking(int timespan = 20)
+        {
+            return DataContext.Set<T>().AsNoTracking().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync(int timespan = 20)
+        {
+            return await DataContext.Set<T>().AsNoTracking().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 从一级缓存获取所有实体(异步)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheAsync(int timespan = 20)
+        {
+            return await DataContext.Set<T>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual EFCachedQueryable<T> GetAllFromL2Cache()
+        {
+            return DataContext.Set<T>().Cacheable();
+        }
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual EFCachedQueryable<T> GetAllFromL2CacheNoTracking()
+        {
+            return DataContext.Set<T>().AsNoTracking().Cacheable();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAll<TDto>()
+        {
+            return DataContext.Set<T>().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAllNoTracking<TDto>()
+        {
+            return DataContext.Set<T>().AsNoTracking().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCache<TDto>(int timespan = 20) where TDto : class
+        {
+            return DataContext.Set<T>().ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheAsync<TDto>(int timespan = 20) where TDto : class
+        {
+            return await DataContext.Set<T>().ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCacheNoTracking<TDto>(int timespan = 20) where TDto : class
+        {
+            return DataContext.Set<T>().AsNoTracking().ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TDto>(int timespan = 20) where TDto : class
+        {
+            return await DataContext.Set<T>().AsNoTracking().ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2Cache<TDto>()
+        {
+            return DataContext.Set<T>().ProjectToQueryable<TDto>().Cacheable();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2CacheNoTracking<TDto>()
+        {
+            return DataContext.Set<T>().AsNoTracking().ProjectToQueryable<TDto>().Cacheable();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> GetAll<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby) : DataContext.Set<T>().OrderByDescending(orderby);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IOrderedQueryable<T> GetAllNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().AsNoTracking().OrderBy(orderby) : DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().OrderByDescending(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return isAsc ? await DataContext.Set<T>().OrderBy(orderby).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().OrderByDescending(orderby).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromCacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return isAsc ? DataContext.Set<T>().AsNoTracking().OrderBy(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20)
+        {
+            return isAsc ? await DataContext.Set<T>().AsNoTracking().OrderBy(orderby).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromL2Cache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).Cacheable() : DataContext.Set<T>().OrderByDescending(orderby).Cacheable();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> GetAllFromL2CacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().AsNoTracking().OrderBy(orderby).Cacheable() : DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).Cacheable();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAll<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).ProjectToQueryable<TDto>() : DataContext.Set<T>().OrderByDescending(orderby).ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> GetAllNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().AsNoTracking().OrderBy(orderby).ProjectToQueryable<TDto>() : DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().OrderByDescending(orderby).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return isAsc ? await DataContext.Set<T>().OrderBy(orderby).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().OrderByDescending(orderby).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromCacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return isAsc ? DataContext.Set<T>().AsNoTracking().OrderBy(orderby).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class
+        {
+            return isAsc ? await DataContext.Set<T>().AsNoTracking().OrderBy(orderby).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2Cache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).ProjectToQueryable<TDto>().Cacheable() : DataContext.Set<T>().OrderByDescending(orderby).ProjectToQueryable<TDto>().Cacheable();
+        }
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> GetAllFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
+        {
+            return isAsc ? DataContext.Set<T>().AsNoTracking().OrderBy(orderby).ProjectToQueryable<TDto>().Cacheable() : DataContext.Set<T>().AsNoTracking().OrderByDescending(orderby).ProjectToQueryable<TDto>().Cacheable();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadEntities(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IOrderedQueryable<T> LoadEntities<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby) : DataContext.Set<T>().Where(@where).OrderByDescending(orderby);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadEntities<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        /// <returns></returns>
+        public virtual IQueryable<TDto> LoadEntities<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).ProjectToQueryable<TDto>() : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCache(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return DataContext.Set<T>().Where(@where).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns></returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return DataContext.Set<T>().Where(@where).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2Cache(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).Cacheable();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).Cacheable() : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).Cacheable();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2Cache<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).Cacheable().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).Cacheable().ProjectToQueryable<TDto>() : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).Cacheable().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<T>> LoadEntitiesAsync(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where)).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IOrderedQueryable<T>> LoadEntitiesAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby) : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby)).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).ProjectToQueryable<TDto>()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).ProjectToQueryable<TDto>() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).ProjectToQueryable<TDto>()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return await WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return isAsc ? await DataContext.Set<T>().Where(where).OrderBy(orderby).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().Where(where).OrderByDescending(orderby).FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return await DataContext.Set<T>().Where(@where).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return isAsc ? await DataContext.Set<T>().Where(@where).OrderBy(orderby).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().Where(@where).OrderByDescending(orderby).ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).Cacheable() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).ProjectToQueryable<TDto>().Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).ProjectToQueryable<TDto>().Cacheable() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).ProjectToQueryable<TDto>().Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadEntitiesNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).AsNoTracking();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IOrderedQueryable<T> LoadEntitiesNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).AsNoTracking().OrderBy(orderby) : DataContext.Set<T>().Where(@where).AsNoTracking().OrderByDescending(orderby);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadEntitiesNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).AsNoTracking().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadEntitiesNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().ProjectToQueryable<TDto>() : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return DataContext.Set<T>().Where(@where).AsNoTracking().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().Where(@where).AsNoTracking().OrderByDescending(orderby).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return DataContext.Set<T>().Where(@where).AsNoTracking().ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2CacheNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).AsNoTracking().Cacheable();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadEntitiesFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().Cacheable() : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().Cacheable();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).AsNoTracking().Cacheable().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().Cacheable().ProjectToQueryable<TDto>() : DataContext.Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().Cacheable().ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IQueryable<T>> LoadEntitiesNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).AsNoTracking()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<T>> LoadEntitiesNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).AsNoTracking() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).AsNoTracking().ProjectToQueryable<TDto>()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().ProjectToQueryable<TDto>() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().ProjectToQueryable<TDto>()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return await DataContext.Set<T>().Where(@where).AsNoTracking().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return isAsc ? await DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return await DataContext.Set<T>().Where(@where).AsNoTracking().ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return isAsc ? await DataContext.Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true) : await DataContext.Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().ProjectToQueryable<TDto>().FromCacheAsync(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).AsNoTracking().Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().Cacheable() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await Task.Run(() => WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).AsNoTracking().ProjectToQueryable<TDto>().Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual async Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return await Task.Run(() => isAsc ? WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderBy(orderby).AsNoTracking().ProjectToQueryable<TDto>().Cacheable() : WebExtension.GetDbContext<DataContext>().Set<T>().Where(@where).OrderByDescending(orderby).AsNoTracking().ProjectToQueryable<TDto>().Cacheable()).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntity(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().FirstOrDefault(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntity<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).FirstOrDefault(where) : DataContext.Set<T>().OrderByDescending(orderby).FirstOrDefault(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntity<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(where).ProjectToFirstOrDefault<TDto>();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntity<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(where).OrderBy(orderby).ProjectToFirstOrDefault<TDto>() : DataContext.Set<T>().Where(where).OrderByDescending(orderby).ProjectToFirstOrDefault<TDto>();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromCache(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return LoadEntitiesFromCache(where, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual T GetFirstEntityFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return LoadEntitiesFromCache(where, orderby, isAsc, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return LoadEntitiesFromCache<TDto>(where, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return LoadEntitiesFromCache<TS, TDto>(where, orderby, isAsc, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromL2Cache(Expression<Func<T, bool>> @where)
+        {
+            return LoadEntitiesFromL2Cache(where).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual T GetFirstEntityFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return LoadEntitiesFromL2Cache(where, orderby, isAsc).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromL2Cache<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return LoadEntitiesFromL2Cache<TDto>(where).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return LoadEntitiesFromL2Cache<TS, TDto>(where, orderby, isAsc).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityAsync(Expression<Func<T, bool>> @where)
+        {
+            return await DataContext.Set<T>().FirstOrDefaultAsync(where).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? await DataContext.Set<T>().OrderBy(orderby).FirstOrDefaultAsync(where).ConfigureAwait(true) : await DataContext.Set<T>().OrderByDescending(orderby).FirstOrDefaultAsync(where).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await DataContext.Set<T>().Where(where).ProjectToFirstOrDefaultAsync<TDto>().ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? await DataContext.Set<T>().Where(where).OrderBy(orderby).ProjectToFirstOrDefaultAsync<TDto>().ConfigureAwait(true) : await DataContext.Set<T>().Where(where).OrderByDescending(orderby).ProjectToFirstOrDefaultAsync<TDto>().ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            var list = await LoadEntitiesFromCacheAsync(@where, timespan).ConfigureAwait(true);
+            return list.FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return (await LoadEntitiesFromCacheAsync(where, orderby, isAsc, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return (await LoadEntitiesFromCacheAsync<TDto>(where, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return (await LoadEntitiesFromCacheAsync<TS, TDto>(where, orderby, isAsc, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheAsync(Expression<Func<T, bool>> @where)
+        {
+            return (await LoadEntitiesFromL2CacheAsync(where)).FirstOrDefault();
+        }
+
+        /// <summary>
+        ///  获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return (await LoadEntitiesFromL2CacheAsync(where, orderby, isAsc)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return (await LoadEntitiesFromL2CacheAsync<TDto>(where)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return (await LoadEntitiesFromL2CacheAsync<TS, TDto>(where, orderby, isAsc)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().AsNoTracking().FirstOrDefault(where);
+        }
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).AsNoTracking().FirstOrDefault(where) : DataContext.Set<T>().OrderByDescending(orderby).AsNoTracking().FirstOrDefault(where);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(where).AsNoTracking().ProjectToFirstOrDefault<TDto>();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? DataContext.Set<T>().Where(where).OrderBy(orderby).AsNoTracking().ProjectToFirstOrDefault<TDto>() : DataContext.Set<T>().Where(where).OrderByDescending(orderby).AsNoTracking().ProjectToFirstOrDefault<TDto>();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return LoadEntitiesFromCacheNoTracking(where, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return LoadEntitiesFromCacheNoTracking(where, orderby, isAsc, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return LoadEntitiesFromCacheNoTracking<TDto>(where, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return LoadEntitiesFromCacheNoTracking<TS, TDto>(where, orderby, isAsc, timespan).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromL2CacheNoTracking(Expression<Func<T, bool>> @where)
+        {
+            return LoadEntitiesFromL2CacheNoTracking(where).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual T GetFirstEntityFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return LoadEntitiesFromL2CacheNoTracking(where, orderby, isAsc).FirstOrDefault();
+        }
+
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual TDto GetFirstEntityFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return LoadEntitiesFromL2CacheNoTracking<TDto>(where).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual TDto GetFirstEntityFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return LoadEntitiesFromL2CacheNoTracking<TS, TDto>(where, orderby, isAsc).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return await DataContext.Set<T>().AsNoTracking().FirstOrDefaultAsync(where).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? await DataContext.Set<T>().OrderBy(orderby).AsNoTracking().FirstOrDefaultAsync(where).ConfigureAwait(true) : await DataContext.Set<T>().OrderByDescending(orderby).AsNoTracking().FirstOrDefaultAsync(where).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return await DataContext.Set<T>().Where(where).AsNoTracking().ProjectToFirstOrDefaultAsync<TDto>().ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return isAsc ? await DataContext.Set<T>().Where(where).OrderBy(orderby).AsNoTracking().ProjectToFirstOrDefaultAsync<TDto>().ConfigureAwait(true) : await DataContext.Set<T>().Where(where).OrderByDescending(orderby).AsNoTracking().ProjectToFirstOrDefaultAsync<TDto>().ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30)
+        {
+            return (await LoadEntitiesFromCacheNoTrackingAsync(where, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<T> GetFirstEntityFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            return (await LoadEntitiesFromCacheNoTrackingAsync(where, orderby, isAsc, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class
+        {
+            return (await LoadEntitiesFromCacheNoTrackingAsync<TDto>(where, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            return (await LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(where, orderby, isAsc, timespan)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where)
+        {
+            return (await LoadEntitiesFromL2CacheNoTrackingAsync(where)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetFirstEntityFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return (await LoadEntitiesFromL2CacheNoTrackingAsync(where, orderby, isAsc)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where)
+        {
+            return (await LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(where)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        public virtual async Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            return (await LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(where, orderby, isAsc)).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 根据ID找实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        public virtual T GetById(object id)
+        {
+            return DataContext.Set<T>().Find(id);
+        }
+
+        /// <summary>
+        /// 根据ID找实体(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        public virtual async Task<T> GetByIdAsync(object id)
+        {
+            return await DataContext.Set<T>().FindAsync(id).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc)
+        {
+            var temp = DataContext.Set<T>().Where(where);
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize);
+        }
+
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadPageEntities<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc)
+        {
+            var temp = DataContext.Set<T>().Where(where);
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>() : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc, int timespan = 30)
+        {
+            var temp = DataContext.Set<T>().Where(where);
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc, int timespan = 30) where TDto : class
+        {
+            var temp = DataContext.Set<T>().Where(where);
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromL2Cache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
+        {
+            var temp = DataContext.Set<T>().Where(where);
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).Cacheable() : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).Cacheable();
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromL2Cache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
+        {
+            var temp = DataContext.Set<T>().Where(where);
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().Cacheable() : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().Cacheable();
+        }
+
+        /// <summary>
+        /// 高效分页查询方法(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<T> LoadPageEntitiesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize);
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IQueryable<TDto> LoadPageEntitiesNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>() : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>();
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromCacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30)
+        {
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromCacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class
+        {
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan))) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().FromCache(CachePolicy.WithDurationExpiration(TimeSpan.FromSeconds(timespan)));
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).Cacheable() : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).Cacheable();
+        }
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        public virtual IEnumerable<TDto> LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        {
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            totalCount = temp.Count();
+            if (pageIndex * pageSize > totalCount)
+            {
+                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
+            }
+
+            if (pageIndex <= 0)
+            {
+                pageIndex = 1;
+            }
+
+            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().Cacheable() : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ProjectToQueryable<TDto>().Cacheable();
+        }
+
+        /// <summary>
+        /// 根据ID删除实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteById(object id)
+        {
+            T t = GetById(id);
+            if (t != null)
+            {
+                DataContext.Entry(t).State = EntityState.Deleted;
+                return true;
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// 删除实体
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteEntity(T t)
+        {
+            DataContext.Entry(t).State = EntityState.Unchanged;
+            DataContext.Entry(t).State = EntityState.Deleted;
+            return true;
+        }
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        public virtual int DeleteEntity(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Where(@where).Delete();
+        }
+
+        /// <summary>
+        /// 根据条件删除实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        public virtual async Task<int> DeleteEntityAsync(Expression<Func<T, bool>> @where)
+        {
+            return await DataContext.Set<T>().Where(@where).DeleteAsync().ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 更新实体
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual bool UpdateEntity(T t)
+        {
+            DataContext.Entry(t).State = EntityState.Modified;
+            return true;
+        }
+
+        /// <summary>
+        /// 根据条件更新实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual int UpdateEntity(Expression<Func<T, bool>> @where, T t)
+        {
+            return DataContext.Set<T>().Where(@where).Update(ts => t);
+        }
+
+        /// <summary>
+        /// 根据条件更新实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        public virtual async Task<int> UpdateEntityAsync(Expression<Func<T, bool>> @where, T t)
+        {
+            return await DataContext.Set<T>().Where(@where).UpdateAsync(ts => t).ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        public virtual T AddEntity(T t)
+        {
+            DataContext.Entry(t).State = EntityState.Added;
+            return t;
+        }
+
+        /// <summary>
+        /// 批量添加实体
+        /// </summary>
+        /// <param name="list">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        public virtual void BulkInsert(IEnumerable<T> list)
+        {
+            DataContext.BulkInsert(list);
+        }
+
+        /// <summary>
+        /// 添加或更新
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        /// <returns></returns>
+        public virtual void AddOrUpdate(Expression<Func<T, object>> exp, params T[] entities)
+        {
+            DataContext.Set<T>().AddOrUpdate(exp, entities);
+        }
+
+        /// <summary>
+        /// 统一保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        public virtual int SaveChanges()
+        {
+            return DataContext.SaveChanges();
+        }
+
+        /// <summary>
+        /// 统一批量保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        public virtual void BulkSaveChanges()
+        {
+            DataContext.BulkSaveChanges();
+        }
+
+        /// <summary>
+        /// 统一保存数据(异步)
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        public virtual async Task<int> SaveChangesAsync()
+        {
+            return await DataContext.SaveChangesAsync().ConfigureAwait(true);
+        }
+
+        /// <summary>
+        /// 判断实体是否在数据库中存在
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>是否存在</returns>
+        public virtual bool Any(Expression<Func<T, bool>> @where)
+        {
+            return DataContext.Set<T>().Any(where);
+        }
+
+        /// <summary>
+        /// 删除多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        public virtual bool DeleteEntities(IEnumerable<T> list)
+        {
+            list.ForEach(t => { DeleteEntity(t); });
+            return true;
+        }
+
+        /// <summary>
+        /// 更新多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        public virtual bool UpdateEntities(IEnumerable<T> list)
+        {
+            list.ForEach(t => { UpdateEntity(t); });
+            return true;
+        }
+
+        /// <summary>
+        /// 添加多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        public virtual IEnumerable<T> AddEntities(IList<T> list)
+        {
+            //foreach (T t in list)
+            //{
+            //    yield return AddEntity(t);
+            //}
+            DataContext.BulkInsert(list);
+            return list;
+        }
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        /// <returns>泛型集合</returns>
+        public virtual DbRawSqlQuery<TS> SqlQuery<TS>(string sql, params SqlParameter[] parameters)
+        {
+            return DataContext.Database.SqlQuery<TS>(sql, parameters);
+        }
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        public virtual DbRawSqlQuery SqlQuery(Type t, string sql, params SqlParameter[] parameters)
+        {
+            return DataContext.Database.SqlQuery(t, sql, parameters);
+        }
+
+        /// <summary>
+        /// 执行DML语句
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="parameters"></param>
+        public virtual void ExecuteSql(string sql, params SqlParameter[] parameters)
+        {
+            DataContext.Database.ExecuteSqlCommand(TransactionalBehavior.EnsureTransaction, sql, parameters);
+        }
+
+        public override void Dispose(bool disposing)
+        {
+            DataContext?.Dispose();
+            DataContext = null;
+        }
+    }
+}

+ 129 - 0
src/DAL/DAL.csproj

@@ -0,0 +1,129 @@
+<?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>{F1A452F8-2757-4130-AECD-4CDCB675419F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>DAL</RootNamespace>
+    <AssemblyName>DAL</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="AngleSharp, Version=0.9.9.0, Culture=neutral, PublicKeyToken=e83494dcdc6d31ea, processorArchitecture=MSIL">
+      <HintPath>..\packages\AngleSharp.0.9.9.2\lib\net45\AngleSharp.dll</HintPath>
+    </Reference>
+    <Reference Include="AutoMapper, Version=7.0.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
+      <HintPath>..\packages\AutoMapper.7.0.1\lib\net45\AutoMapper.dll</HintPath>
+    </Reference>
+    <Reference Include="AutoMapper.EF6, Version=1.1.1.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\AutoMapper.EF6.1.1.1\lib\net45\AutoMapper.EF6.dll</HintPath>
+    </Reference>
+    <Reference Include="DelegateDecompiler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=93b26a10a04705bd, processorArchitecture=MSIL">
+      <HintPath>..\packages\DelegateDecompiler.0.24.0\lib\net45\DelegateDecompiler.dll</HintPath>
+    </Reference>
+    <Reference Include="DelegateDecompiler.EntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=93b26a10a04705bd, processorArchitecture=MSIL">
+      <HintPath>..\packages\DelegateDecompiler.EntityFramework.0.24.0\lib\net45\DelegateDecompiler.EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EFSecondLevelCache, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\EFSecondLevelCache.1.2.0.0\lib\net45\EFSecondLevelCache.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.Extended, Version=6.0.0.0, Culture=neutral, PublicKeyToken=05b7e29bdd433584, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.Extended.6.1.0.168\lib\net45\EntityFramework.Extended.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="HtmlSanitizer, Version=3.0.0.0, Culture=neutral, PublicKeyToken=61c49a1a9e79cc28, processorArchitecture=MSIL">
+      <HintPath>..\packages\HtmlSanitizer.4.0.185\lib\net45\HtmlSanitizer.dll</HintPath>
+    </Reference>
+    <Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="Mono.Reflection, Version=1.1.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Reflection.1.1.0.0\lib\Mono.Reflection.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="StackExchange.Redis, Version=1.2.6.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\StackExchange.Redis.1.2.6\lib\net45\StackExchange.Redis.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.ComponentModel.DataAnnotations" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.IO.Compression" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
+    </Reference>
+    <Reference Include="Z.EntityFramework.Extensions, Version=3.15.5.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Z.EntityFramework.Extensions.3.15.5\lib\net45\Z.EntityFramework.Extensions.dll</HintPath>
+    </Reference>
+    <Reference Include="Z.EntityFramework.Plus.EF6, Version=1.8.4.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Z.EntityFramework.Plus.EF6.1.8.4\lib\net45\Z.EntityFramework.Plus.EF6.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BaseDal.cs" />
+    <Compile Include="Dals.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Dals.tt</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Masuit.Tools\Masuit.Tools\Masuit.Tools.csproj">
+      <Project>{275d5a0d-c49c-497e-a4b5-f40285c2495f}</Project>
+      <Name>Masuit.Tools</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\IDAL\IDAL.csproj">
+      <Project>{7997fb01-c9c1-4793-a430-9ca3c3852b37}</Project>
+      <Name>IDAL</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Models\Models.csproj">
+      <Project>{5400CA01-CBCF-4531-A388-3057393D5B4F}</Project>
+      <Name>Models</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Dals.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>Dals.cs</LastGenOutput>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 29 - 0
src/DAL/Dals.cs

@@ -0,0 +1,29 @@
+
+using IDAL;
+using Models.Entity;
+using System;
+namespace DAL
+{
+	public partial class BroadcastDal :BaseDal<Broadcast>,IBroadcastDal{}
+	public partial class CategoryDal :BaseDal<Category>,ICategoryDal{}
+	public partial class CommentDal :BaseDal<Comment>,ICommentDal{}
+	public partial class ContactsDal :BaseDal<Contacts>,IContactsDal{}
+	public partial class DonateDal :BaseDal<Donate>,IDonateDal{}
+	public partial class InternalMessageDal :BaseDal<InternalMessage>,IInternalMessageDal{}
+	public partial class InterviewDal :BaseDal<Interview>,IInterviewDal{}
+	public partial class InterviewDetailDal :BaseDal<InterviewDetail>,IInterviewDetailDal{}
+	public partial class IssueDal :BaseDal<Issue>,IIssueDal{}
+	public partial class LeaveMessageDal :BaseDal<LeaveMessage>,ILeaveMessageDal{}
+	public partial class LinksDal :BaseDal<Links>,ILinksDal{}
+	public partial class LoginRecordDal :BaseDal<LoginRecord>,ILoginRecordDal{}
+	public partial class MenuDal :BaseDal<Menu>,IMenuDal{}
+	public partial class MiscDal :BaseDal<Misc>,IMiscDal{}
+	public partial class NoticeDal :BaseDal<Notice>,INoticeDal{}
+	public partial class PostDal :BaseDal<Post>,IPostDal{}
+	public partial class PostAccessRecordDal :BaseDal<PostAccessRecord>,IPostAccessRecordDal{}
+	public partial class PostHistoryVersionDal :BaseDal<PostHistoryVersion>,IPostHistoryVersionDal{}
+	public partial class SearchDetailsDal :BaseDal<SearchDetails>,ISearchDetailsDal{}
+	public partial class SeminarDal :BaseDal<Seminar>,ISeminarDal{}
+	public partial class SystemSettingDal :BaseDal<SystemSetting>,ISystemSettingDal{}
+	public partial class UserInfoDal :BaseDal<UserInfo>,IUserInfoDal{}
+}

+ 24 - 0
src/DAL/Dals.tt

@@ -0,0 +1,24 @@
+<#@ template language="C#" debug="false" hostspecific="true"#>
+<#@ include file="EF.Utility.CS.ttinclude"#>
+<#@output extension=".cs"#>
+<#
+CodeGenerationTools code = new CodeGenerationTools(this);
+MetadataLoader loader = new MetadataLoader(this);
+CodeRegion region = new CodeRegion(this, 1);
+MetadataTools ef = new MetadataTools(this);
+string inputFile = @"..\\ModelCodeGenerate\\Model.edmx";//EF模型路径
+EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
+string namespaceName = code.VsNamespaceSuggestion();
+EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
+#>
+using IDAL;
+using Models.Entity;
+using System;
+namespace DAL
+{
+<#
+foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
+{#>
+	public partial class <#=entity.Name#>Dal :BaseDal<<#=entity.Name#>>,I<#=entity.Name#>Dal{}
+<#}#>
+}

+ 36 - 0
src/DAL/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("DAL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DAL")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("f1a452f8-2757-4130-aecd-4cdcb675419f")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 20 - 0
src/DAL/packages.config

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="AngleSharp" version="0.9.9.2" targetFramework="net45" />
+  <package id="AutoMapper" version="7.0.1" targetFramework="net45" />
+  <package id="AutoMapper.EF6" version="1.1.1" targetFramework="net45" />
+  <package id="DelegateDecompiler" version="0.24.0" targetFramework="net45" />
+  <package id="DelegateDecompiler.EntityFramework" version="0.24.0" targetFramework="net45" />
+  <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
+  <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
+  <package id="EntityFramework.Extended" version="6.1.0.168" targetFramework="net45" />
+  <package id="EntityFramework.zh-Hans" version="6.2.0" targetFramework="net45" />
+  <package id="HtmlSanitizer" version="4.0.185" targetFramework="net45" />
+  <package id="Mono.Reflection" version="1.1.0.0" targetFramework="net45" />
+  <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net45" />
+  <package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
+  <package id="StackExchange.Redis" version="1.2.6" targetFramework="net45" />
+  <package id="System.ValueTuple" version="4.5.0" targetFramework="net45" />
+  <package id="Z.EntityFramework.Extensions" version="3.15.5" targetFramework="net45" />
+  <package id="Z.EntityFramework.Plus.EF6" version="1.8.4" targetFramework="net45" />
+</packages>

+ 44 - 0
src/Factory/Factory.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+
+namespace DALFactory
+{
+    /// <summary>
+    /// 反射工厂
+    /// </summary>
+    public static class Factory
+    {
+        /// <summary>
+        /// 根据配置文件中的方式进行反射创建对象
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="fullNamespace">程序集全命名空间</param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        public static T CreateInstance<T>(string fullNamespace)
+        {
+            try
+            {
+                string dalNameSpace = ConfigurationManager.AppSettings["DalNameSpace"] ?? "DAL";//根据命名空间创建实例对象
+                Assembly ass = Assembly.Load(dalNameSpace);
+                return (T)ass.CreateInstance(fullNamespace);
+            }
+            catch
+            {
+                try
+                {
+                    string dalPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", ConfigurationManager.AppSettings["DalPath"] ?? "DAL.dll");//根据程序集路径创建实例对象
+                    Assembly ass = Assembly.LoadFile(dalPath);
+                    return (T)ass.CreateInstance(fullNamespace);
+                }
+                catch
+                {
+                    //都出错则往外抛异常
+                    throw new Exception("找不到程序集");
+                }
+            }
+        }
+    }
+}

+ 45 - 0
src/Factory/Factory.csproj

@@ -0,0 +1,45 @@
+<?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>{1363B3D8-457C-4A8C-BAD4-228BC9141A4C}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Factory</RootNamespace>
+    <AssemblyName>Factory</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Factory.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 81 - 0
src/Factory/ObjectPool.cs

@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+
+namespace DALFactory
+{
+    /// <summary>
+    /// 对象池
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    public class ObjectPool<T> : ConcurrentQueue<T> where T : class
+    {
+        private int Limit { get; set; }
+
+        public ObjectPool(int limit = 32)
+        {
+            Limit = limit;
+        }
+
+        public ObjectPool(List<T> list) : base(list)
+        {
+            Limit = list.Count;
+        }
+
+        public new void Enqueue(T item)
+        {
+            if (Count >= Limit)
+            {
+                TryDequeue(out var _);
+            }
+
+            base.Enqueue(item);
+        }
+        public T Dequeue(string fullNamespace)
+        {
+            if (Count < 1 || IsEmpty)
+            {
+                for (int i = 0; i < Limit; i++)
+                {
+                    Enqueue(GetInstance(fullNamespace));
+                }
+            }
+            TryDequeue(out var t);
+            return t ?? GetInstance(fullNamespace);
+        }
+
+        /// <summary>
+        /// 根据配置文件中的方式进行反射创建对象
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="fullNamespace">程序集全命名空间</param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        public static T GetInstance(string fullNamespace)
+        {
+            try
+            {
+                string DalNameSpace = ConfigurationManager.AppSettings["DalNameSpace"] ?? "DAL";//根据命名空间创建实例对象
+                Assembly ass = Assembly.Load(DalNameSpace);
+                return (T)ass.CreateInstance(fullNamespace);
+            }
+            catch (Exception)
+            {
+                try
+                {
+                    string DalPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", ConfigurationManager.AppSettings["DalPath"] ?? "DAL.dll");//根据程序集路径创建实例对象
+                    Assembly ass = Assembly.LoadFile(DalPath);
+                    return (T)ass.CreateInstance(fullNamespace);
+                }
+                catch (Exception)
+                {
+                    //都出错则往外抛异常
+                    throw new Exception("找不到程序集");
+                }
+            }
+        }
+    }
+}

+ 36 - 0
src/Factory/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Factory")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Factory")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("d927561b-5ed4-4599-8209-16f9d1f5461d")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 25 - 0
src/IBLL/App.config

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+    
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
+      <parameters>
+        <parameter value="mssqllocaldb" />
+      </parameters>
+    </defaultConnectionFactory>
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+    </providers>
+  </entityFramework>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-7.0.1.0" newVersion="7.0.1.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>

+ 85 - 0
src/IBLL/IBLL.csproj

@@ -0,0 +1,85 @@
+<?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>{939493B4-A47C-43E2-99E3-92459CD0EB1E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>IBLL</RootNamespace>
+    <AssemblyName>IBLL</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <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' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="EFSecondLevelCache, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\EFSecondLevelCache.1.2.0.0\lib\net45\EFSecondLevelCache.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.ComponentModel.DataAnnotations" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="IBaseBll.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>IBaseBll.tt</DependentUpon>
+    </Compile>
+    <Compile Include="ICommentBll.cs" />
+    <Compile Include="ILeaveMessageBll.cs" />
+    <Compile Include="IMenuBll.cs" />
+    <Compile Include="IPostBll.cs" />
+    <Compile Include="IUserInfoBll.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="IBaseBll.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>IBaseBll.cs</LastGenOutput>
+    </Content>
+    <Content Include="readme.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\IDAL\IDAL.csproj">
+      <Project>{7997FB01-C9C1-4793-A430-9CA3C3852B37}</Project>
+      <Name>IDAL</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Models\Models.csproj">
+      <Project>{5400CA01-CBCF-4531-A388-3057393D5B4F}</Project>
+      <Name>Models</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 1643 - 0
src/IBLL/IBaseBll.cs

@@ -0,0 +1,1643 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Data.Entity.Infrastructure;
+using System.Data.SqlClient;
+using System.Threading.Tasks;
+using EFSecondLevelCache;
+using Models.Entity;
+namespace IBLL
+{
+    public interface IBaseBll<T>
+    {
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll();
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAllNoTracking();
+
+        /// <summary>
+        /// 从一级缓存获取所有实体
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache(int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking(int timespan = 20);
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从一级缓存获取所有实体(异步)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2Cache();
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2CacheNoTracking();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAllNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2Cache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2CacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntities(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntities<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntities<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        /// <returns></returns>
+        IQueryable<TDto> LoadEntities<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns></returns>
+        IEnumerable<T> LoadEntitiesFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IOrderedQueryable<T>> LoadEntitiesAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntitiesNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> LoadEntitiesNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntity<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntity<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        ///  获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID找实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        T GetById(object id);
+
+        /// <summary>
+        /// 根据ID找实体(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        Task<T> GetByIdAsync(object id);
+
+        /// <summary>
+        /// 高效分页查询方法
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true);
+
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntities<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true, int timespan = 30);
+
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2Cache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2Cache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntitiesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntitiesNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID删除实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        bool DeleteById(object id);
+
+        /// <summary>
+        /// 根据ID删除实体并保存
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        bool DeleteByIdSaved(object id);
+
+        /// <summary>
+        /// 根据ID删除实体并保存(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteByIdSavedAsync(object id);
+
+        /// <summary>
+        /// 删除实体并保存
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntity(T t);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        int DeleteEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        int DeleteEntitySaved(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntitySavedAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 删除实体并保存
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntitySaved(T t);
+
+        /// <summary>
+        /// 删除实体并保存(异步)
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntitySavedAsync(T t);
+
+        /// <summary>
+        /// 更新实体
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntity(T t);
+
+        /// <summary>
+        /// 更新实体并保存
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntitySaved(T t);
+
+        /// <summary>
+        /// 更新实体并保存(异步)
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntitySavedAsync(T t);
+
+        /// <summary>
+        /// 根据条件更新实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        int UpdateEntity(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 根据条件更新实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntityAsync(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        T AddEntity(T t);
+
+        /// <summary>
+        /// 添加实体并保存
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        T AddEntitySaved(T t);
+
+        /// <summary>
+        /// 添加实体并保存(异步)
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        Task<int> AddEntitySavedAsync(T t);
+
+        /// <summary>
+        /// 添加或更新
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        void AddOrUpdate(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新并保存
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        int AddOrUpdateSaved(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新并保存(异步)
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        Task<int> AddOrUpdateSavedAsync(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 统一保存的方法
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        int SaveChanges();
+
+        /// <summary>
+        /// 统一保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        Task<int> SaveChangesAsync();
+
+        /// <summary>
+        /// 判断实体是否在数据库中存在
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>是否存在</returns>
+        bool Any(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 删除多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 删除多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntitiesSaved(IEnumerable<T> list);
+
+        /// <summary>
+        /// 删除多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntitiesSavedAsync(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntitiesSaved(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntitiesSavedAsync(IEnumerable<T> list);
+
+        /// <summary>
+        /// 添加多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        IEnumerable<T> AddEntities(IList<T> list);
+
+        /// <summary>
+        /// 添加多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        Task<IEnumerable<T>> AddEntitiesAsync(IList<T> list);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        /// <returns>泛型集合</returns>
+        DbRawSqlQuery<TS> SqlQuery<TS>(string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        DbRawSqlQuery SqlQuery(Type t, string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行DML语句
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="parameters"></param>
+        void ExecuteSql(string sql, params SqlParameter[] parameters);
+        
+        /// <summary>
+        /// 批量添加实体
+        /// </summary>
+        /// <param name="list">需要添加的实体</param>
+        void BulkInsert(IEnumerable<T> list);
+
+        /// <summary>
+        /// 统一批量保存数据
+        /// </summary>
+        void BulkSaveChanges();
+    }
+	
+	public partial interface IBroadcastBll : IBaseBll<Broadcast>{}   
+	
+	public partial interface ICategoryBll : IBaseBll<Category>{}   
+	
+	public partial interface ICommentBll : IBaseBll<Comment>{}   
+	
+	public partial interface IContactsBll : IBaseBll<Contacts>{}   
+	
+	public partial interface IDonateBll : IBaseBll<Donate>{}   
+	
+	public partial interface IInternalMessageBll : IBaseBll<InternalMessage>{}   
+	
+	public partial interface IInterviewBll : IBaseBll<Interview>{}   
+	
+	public partial interface IInterviewDetailBll : IBaseBll<InterviewDetail>{}   
+	
+	public partial interface IIssueBll : IBaseBll<Issue>{}   
+	
+	public partial interface ILeaveMessageBll : IBaseBll<LeaveMessage>{}   
+	
+	public partial interface ILinksBll : IBaseBll<Links>{}   
+	
+	public partial interface ILoginRecordBll : IBaseBll<LoginRecord>{}   
+	
+	public partial interface IMenuBll : IBaseBll<Menu>{}   
+	
+	public partial interface IMiscBll : IBaseBll<Misc>{}   
+	
+	public partial interface INoticeBll : IBaseBll<Notice>{}   
+	
+	public partial interface IPostBll : IBaseBll<Post>{}   
+	
+	public partial interface IPostAccessRecordBll : IBaseBll<PostAccessRecord>{}   
+	
+	public partial interface IPostHistoryVersionBll : IBaseBll<PostHistoryVersion>{}   
+	
+	public partial interface ISearchDetailsBll : IBaseBll<SearchDetails>{}   
+	
+	public partial interface ISeminarBll : IBaseBll<Seminar>{}   
+	
+	public partial interface ISystemSettingBll : IBaseBll<SystemSetting>{}   
+	
+	public partial interface IUserInfoBll : IBaseBll<UserInfo>{}   
+	
+}

+ 1615 - 0
src/IBLL/IBaseBll.tt

@@ -0,0 +1,1615 @@
+<#@ template language="C#" debug="false" hostspecific="true"#>
+<#@ include file="EF.Utility.CS.ttinclude"#>
+<#@ output extension=".cs"#>
+<#
+CodeGenerationTools code = new CodeGenerationTools(this);
+MetadataLoader loader = new MetadataLoader(this);
+CodeRegion region = new CodeRegion(this, 1);
+MetadataTools ef = new MetadataTools(this);
+string inputFile = @"..\\ModelCodeGenerate\\Model.edmx";//EF模型路径
+EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
+string namespaceName = code.VsNamespaceSuggestion();
+EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
+#>
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Data.Entity.Infrastructure;
+using System.Data.SqlClient;
+using System.Threading.Tasks;
+using EFSecondLevelCache;
+using Models.Entity;
+namespace IBLL
+{
+    public interface IBaseBll<T>
+    {
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll();
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAllNoTracking();
+
+        /// <summary>
+        /// 从一级缓存获取所有实体
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache(int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking(int timespan = 20);
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从一级缓存获取所有实体(异步)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2Cache();
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2CacheNoTracking();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAllNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2Cache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2CacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntities(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntities<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntities<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        /// <returns></returns>
+        IQueryable<TDto> LoadEntities<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns></returns>
+        IEnumerable<T> LoadEntitiesFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IOrderedQueryable<T>> LoadEntitiesAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntitiesNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> LoadEntitiesNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntity<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntity<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        ///  获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID找实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        T GetById(object id);
+
+        /// <summary>
+        /// 根据ID找实体(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        Task<T> GetByIdAsync(object id);
+
+        /// <summary>
+        /// 高效分页查询方法
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true);
+
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntities<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true, int timespan = 30);
+
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2Cache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2Cache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntitiesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntitiesNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID删除实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        bool DeleteById(object id);
+
+        /// <summary>
+        /// 根据ID删除实体并保存
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        bool DeleteByIdSaved(object id);
+
+        /// <summary>
+        /// 根据ID删除实体并保存(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteByIdSavedAsync(object id);
+
+        /// <summary>
+        /// 删除实体并保存
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntity(T t);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        int DeleteEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        int DeleteEntitySaved(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntitySavedAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 删除实体并保存
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntitySaved(T t);
+
+        /// <summary>
+        /// 删除实体并保存(异步)
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntitySavedAsync(T t);
+
+        /// <summary>
+        /// 更新实体
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntity(T t);
+
+        /// <summary>
+        /// 更新实体并保存
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntitySaved(T t);
+
+        /// <summary>
+        /// 更新实体并保存(异步)
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntitySavedAsync(T t);
+
+        /// <summary>
+        /// 根据条件更新实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        int UpdateEntity(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 根据条件更新实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntityAsync(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        T AddEntity(T t);
+
+        /// <summary>
+        /// 添加实体并保存
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        T AddEntitySaved(T t);
+
+        /// <summary>
+        /// 添加实体并保存(异步)
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        Task<int> AddEntitySavedAsync(T t);
+
+        /// <summary>
+        /// 添加或更新
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        void AddOrUpdate(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新并保存
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        int AddOrUpdateSaved(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新并保存(异步)
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        Task<int> AddOrUpdateSavedAsync(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 统一保存的方法
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        int SaveChanges();
+
+        /// <summary>
+        /// 统一保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        Task<int> SaveChangesAsync();
+
+        /// <summary>
+        /// 判断实体是否在数据库中存在
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>是否存在</returns>
+        bool Any(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 删除多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 删除多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntitiesSaved(IEnumerable<T> list);
+
+        /// <summary>
+        /// 删除多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntitiesSavedAsync(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntitiesSaved(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntitiesSavedAsync(IEnumerable<T> list);
+
+        /// <summary>
+        /// 添加多个实体并保存
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        IEnumerable<T> AddEntities(IList<T> list);
+
+        /// <summary>
+        /// 添加多个实体并保存(异步)
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        Task<IEnumerable<T>> AddEntitiesAsync(IList<T> list);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        /// <returns>泛型集合</returns>
+        DbRawSqlQuery<TS> SqlQuery<TS>(string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        DbRawSqlQuery SqlQuery(Type t, string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行DML语句
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="parameters"></param>
+        void ExecuteSql(string sql, params SqlParameter[] parameters);
+        
+        /// <summary>
+        /// 批量添加实体
+        /// </summary>
+        /// <param name="list">需要添加的实体</param>
+        void BulkInsert(IEnumerable<T> list);
+
+        /// <summary>
+        /// 统一批量保存数据
+        /// </summary>
+        void BulkSaveChanges();
+    }
+<#
+foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
+{#>	
+	public partial interface I<#=entity.Name#>Bll : IBaseBll<<#=entity.Name#>>{}   
+<#}#>	
+}

+ 22 - 0
src/IBLL/ICommentBll.cs

@@ -0,0 +1,22 @@
+using System.Data.Entity.Infrastructure;
+using Models.Entity;
+
+namespace IBLL
+{
+    public partial interface ICommentBll
+    {
+        /// <summary>
+        /// 通过存储过程获得自己以及自己所有的子元素集合
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        DbRawSqlQuery<Comment> GetSelfAndAllChildrenCommentsByParentId(int id);
+
+        /// <summary>
+        /// 根据无级子级找顶级父级评论
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        int GetParentCommentIdByChildId(int id);
+    }
+}

+ 22 - 0
src/IBLL/ILeaveMessageBll.cs

@@ -0,0 +1,22 @@
+using System.Data.Entity.Infrastructure;
+using Models.Entity;
+
+namespace IBLL
+{
+    public partial interface ILeaveMessageBll
+    {
+        /// <summary>
+        /// 通过存储过程获得自己以及自己所有的子元素集合
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        DbRawSqlQuery<LeaveMessage> GetSelfAndAllChildrenMessagesByParentId(int id);
+
+        /// <summary>
+        /// 根据无级子级找顶级父级留言
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        int GetParentMessageIdByChildId(int id);
+    }
+}

+ 16 - 0
src/IBLL/IMenuBll.cs

@@ -0,0 +1,16 @@
+using System.Data.Entity.Infrastructure;
+using Models.Entity;
+
+namespace IBLL
+{
+    public partial interface IMenuBll
+    {
+        /// <summary>
+        /// 通过存储过程获得自己以及自己所有的子元素集合
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        DbRawSqlQuery<Menu> GetChildrenMenusByParentId(int id);
+
+    }
+}

+ 25 - 0
src/IBLL/IPostBll.cs

@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using Models.DTO;
+
+namespace IBLL
+{
+    public partial interface IPostBll
+    {
+        /// <summary>
+        /// 移动分类
+        /// </summary>
+        /// <param name="pid">文章ID</param>
+        /// <param name="cid">分类ID</param>
+        /// <returns></returns>
+        bool MoveToCategory(int pid, int cid);
+    }
+
+    public partial interface IMenuBll
+    {
+        /// <summary>
+        /// 获取菜单
+        /// </summary>
+        /// <returns></returns>
+        IList<MenuOutputDto> GetMenus();
+    }
+}

+ 61 - 0
src/IBLL/IUserInfoBll.cs

@@ -0,0 +1,61 @@
+using Models.DTO;
+using Models.Entity;
+
+namespace IBLL
+{
+    public partial interface IUserInfoBll
+    {
+        /// <summary>
+        /// 根据用户名获取
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        UserInfo GetByUsername(string name);
+
+        /// <summary>
+        /// 登录
+        /// </summary>
+        /// <param name="username"></param>
+        /// <param name="password"></param>
+        /// <returns></returns>
+        UserInfoOutputDto Login(string username, string password);
+
+        /// <summary>
+        /// 注册
+        /// </summary>
+        /// <param name="userInfo"></param>
+        /// <returns></returns>
+        UserInfo Register(UserInfo userInfo);
+
+        /// <summary>
+        /// 检查用户名是否存在
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        bool UsernameExist(string name);
+
+        /// <summary>
+        /// 检查邮箱是否存在
+        /// </summary>
+        /// <param name="email"></param>
+        /// <returns></returns>
+        bool EmailExist(string email);
+
+        /// <summary>
+        /// 修改密码
+        /// </summary>
+        /// <param name="name">用户名,邮箱或者电话号码</param>
+        /// <param name="oldPwd">旧密码</param>
+        /// <param name="newPwd">新密码</param>
+        /// <returns></returns>
+        bool ChangePassword(string name, string oldPwd, string newPwd);
+        bool ChangePassword(int id, string oldPwd, string newPwd);
+
+        /// <summary>
+        /// 重置密码
+        /// </summary>
+        /// <returns></returns>
+        bool ResetPassword(string name, string newPwd = "123456");
+
+    }
+}

+ 36 - 0
src/IBLL/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("IBLL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("IBLL")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("939493b4-a47c-43e2-99e3-92459cd0eb1e")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 5 - 0
src/IBLL/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
+  <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
+</packages>

+ 70 - 0
src/IBLL/readme.txt

@@ -0,0 +1,70 @@
+EFSecondLevelCache
+=======
+Entity Framework 6.x Second Level Caching Library.
+
+Second level caching is a query cache. The results of EF commands will be stored in the cache,
+so that the same EF commands will retrieve their data from the cache rather than executing them
+against the database again.
+
+
+Usage:
+1- Setting up the cache invalidation by overriding the SaveChanges method to prevent stale reads:
+
+namespace EFSecondLevelCache.TestDataLayer.DataLayer
+{
+	public class SampleContext : DbContext
+	{
+		// public DbSet<Product> Products { get; set; }
+
+		public SampleContext()
+			: base("connectionString1")
+		{
+		}
+
+		public override int SaveChanges()
+		{
+			return SaveAllChanges(invalidateCacheDependencies: true);
+		}
+
+		public int SaveAllChanges(bool invalidateCacheDependencies = true)
+		{
+			var changedEntityNames = getChangedEntityNames();
+			var result = base.SaveChanges();
+			if (invalidateCacheDependencies)
+			{
+				new EFCacheServiceProvider().InvalidateCacheDependencies(changedEntityNames);
+			}
+			return result;
+		}
+
+		private string[] getChangedEntityNames()
+		{
+			// Updated version of this method: \EFSecondLevelCache\EFSecondLevelCache.Tests\EFSecondLevelCache.TestDataLayer\DataLayer\SampleContext.cs
+			return this.ChangeTracker.Entries()
+				.Where(x => x.State == EntityState.Added ||
+							x.State == EntityState.Modified ||
+							x.State == EntityState.Deleted)
+				.Select(x => System.Data.Entity.Core.Objects.ObjectContext.GetObjectType(x.Entity.GetType()).FullName)
+				.Distinct()
+				.ToArray();
+		}
+	}
+}
+
+Sometimes you don't want to invalidate the cache when non important properties such as NumberOfViews are updated.
+In these cases, try SaveAllChanges(invalidateCacheDependencies: false), before updating the data.
+
+2- Then to cache the results of the normal queries like:
+var products = context.Products.Include(x => x.Tags).FirstOrDefault();
+
+We can use the new `Cacheable()` extension method:
+var products = context.Products.Include(x => x.Tags).Cacheable().FirstOrDefault(); // Async methods are supported too.
+
+
+Notes:
+Good candidates for query caching are global site's settings, list of public articles or comments
+and not frequently changed, private or specific data to each user.
+If a page requires authentication, its data shouldn't be cached.
+
+Project's Url:
+https://github.com/VahidN/EFSecondLevelCache

+ 25 - 0
src/IDAL/App.config

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+    
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
+      <parameters>
+        <parameter value="mssqllocaldb" />
+      </parameters>
+    </defaultConnectionFactory>
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+    </providers>
+  </entityFramework>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-7.0.1.0" newVersion="7.0.1.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>

+ 1526 - 0
src/IDAL/IBaseDal.cs

@@ -0,0 +1,1526 @@
+
+ 
+using System;
+using System.Collections.Generic;
+using System.Data.Entity.Infrastructure;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using EFSecondLevelCache;
+using Models.Entity;
+namespace IDAL
+{   
+	public interface IBaseDal<T> : IDisposable where T : class, new()
+    {
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll();
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAllNoTracking();
+
+        /// <summary>
+        /// 从一级缓存获取所有实体
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache(int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking(int timespan = 20);
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从一级缓存获取所有实体(异步)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2Cache();
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2CacheNoTracking();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> GetAllNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2Cache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2CacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntities(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> LoadEntities<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntities<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        /// <returns></returns>
+        IQueryable<TDto> LoadEntities<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns></returns>
+        IEnumerable<T> LoadEntitiesFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IOrderedQueryable<T>> LoadEntitiesAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntitiesNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> LoadEntitiesNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntity<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntity<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        ///  获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID找实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        T GetById(object id);
+
+        /// <summary>
+        /// 根据ID找实体(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        Task<T> GetByIdAsync(object id);
+
+        /// <summary>
+        /// 高效分页查询方法
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
+
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntities<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc, int timespan = 30);
+
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2Cache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2Cache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
+
+        /// <summary>
+        /// 高效分页查询方法(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntitiesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntitiesNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID删除实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        bool DeleteById(object id);
+
+        /// <summary>
+        /// 删除实体
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntity(T t);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        int DeleteEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 更新实体
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntity(T t);
+
+        /// <summary>
+        /// 根据条件更新实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        int UpdateEntity(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 根据条件更新实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntityAsync(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        T AddEntity(T t);
+
+        /// <summary>
+        /// 批量添加实体
+        /// </summary>
+        /// <param name="list">需要添加的实体</param>
+        void BulkInsert(IEnumerable<T> list);
+
+        /// <summary>
+        /// 添加或更新
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        void AddOrUpdate(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 统一保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        int SaveChanges();
+
+        /// <summary>
+        /// 统一批量保存数据
+        /// </summary>
+        void BulkSaveChanges();
+
+        /// <summary>
+        /// 统一保存数据(异步)
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        Task<int> SaveChangesAsync();
+
+        /// <summary>
+        /// 判断实体是否在数据库中存在
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>是否存在</returns>
+        bool Any(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 删除多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 添加多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        IEnumerable<T> AddEntities(IList<T> list);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        /// <returns>泛型集合</returns>
+        DbRawSqlQuery<TS> SqlQuery<TS>(string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        DbRawSqlQuery SqlQuery(Type t, string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行DML语句
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="parameters"></param>
+        void ExecuteSql(string sql, params SqlParameter[] parameters);
+    }
+
+	
+	public partial interface IBroadcastDal :IBaseDal<Broadcast>{}
+	
+	public partial interface ICategoryDal :IBaseDal<Category>{}
+	
+	public partial interface ICommentDal :IBaseDal<Comment>{}
+	
+	public partial interface IContactsDal :IBaseDal<Contacts>{}
+	
+	public partial interface IDonateDal :IBaseDal<Donate>{}
+	
+	public partial interface IInternalMessageDal :IBaseDal<InternalMessage>{}
+	
+	public partial interface IInterviewDal :IBaseDal<Interview>{}
+	
+	public partial interface IInterviewDetailDal :IBaseDal<InterviewDetail>{}
+	
+	public partial interface IIssueDal :IBaseDal<Issue>{}
+	
+	public partial interface ILeaveMessageDal :IBaseDal<LeaveMessage>{}
+	
+	public partial interface ILinksDal :IBaseDal<Links>{}
+	
+	public partial interface ILoginRecordDal :IBaseDal<LoginRecord>{}
+	
+	public partial interface IMenuDal :IBaseDal<Menu>{}
+	
+	public partial interface IMiscDal :IBaseDal<Misc>{}
+	
+	public partial interface INoticeDal :IBaseDal<Notice>{}
+	
+	public partial interface IPostDal :IBaseDal<Post>{}
+	
+	public partial interface IPostAccessRecordDal :IBaseDal<PostAccessRecord>{}
+	
+	public partial interface IPostHistoryVersionDal :IBaseDal<PostHistoryVersion>{}
+	
+	public partial interface ISearchDetailsDal :IBaseDal<SearchDetails>{}
+	
+	public partial interface ISeminarDal :IBaseDal<Seminar>{}
+	
+	public partial interface ISystemSettingDal :IBaseDal<SystemSetting>{}
+	
+	public partial interface IUserInfoDal :IBaseDal<UserInfo>{}
+	
+}

+ 1495 - 0
src/IDAL/IBaseDal.tt

@@ -0,0 +1,1495 @@
+<#@ template language="C#" debug="false" hostspecific="true"#>
+<#@ include file="EF.Utility.CS.ttinclude"#>
+<#@ output extension=".cs"#> 
+<# CodeGenerationTools code = new CodeGenerationTools(this);
+MetadataLoader loader = new MetadataLoader(this);
+CodeRegion region = new CodeRegion(this, 1);
+MetadataTools ef = new MetadataTools(this);
+string inputFile = @"..\\ModelCodeGenerate\\Model.edmx";//EF模型路径
+EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
+string namespaceName = code.VsNamespaceSuggestion();
+EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this); #>
+using System;
+using System.Collections.Generic;
+using System.Data.Entity.Infrastructure;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using EFSecondLevelCache;
+using Models.Entity;
+namespace IDAL
+{   
+	public interface IBaseDal<T> : IDisposable where T : class, new()
+    {
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll();
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAllNoTracking();
+
+        /// <summary>
+        /// 从一级缓存获取所有实体
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache(int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking(int timespan = 20);
+        /// <summary>
+        /// 获取所有实体(不跟踪)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从一级缓存获取所有实体(异步)
+        /// </summary>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync(int timespan = 20);
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2Cache();
+
+        /// <summary>
+        /// 从二级缓存获取所有实体
+        /// </summary>
+        /// <returns>还未执行的SQL语句</returns>
+        EFCachedQueryable<T> GetAllFromL2CacheNoTracking();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TDto>(int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TDto>();
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> GetAll<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> GetAllNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromCacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> GetAllFromCacheNoTrackingAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2Cache<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> GetAllFromL2CacheNoTracking<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAll<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> GetAllNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromCacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> GetAllFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 20) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2Cache<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 获取所有实体
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> GetAllFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntities(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> LoadEntities<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntities<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        /// <returns></returns>
+        IQueryable<TDto> LoadEntities<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns></returns>
+        IEnumerable<T> LoadEntitiesFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IOrderedQueryable<T>> LoadEntitiesAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadEntitiesNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IOrderedQueryable<T> LoadEntitiesNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadEntitiesNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadEntitiesFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadEntitiesFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<T>> LoadEntitiesNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IQueryable<TDto>> LoadEntitiesNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<T>> LoadEntitiesFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体集合</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<IEnumerable<TDto>> LoadEntitiesFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        ///  基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<T>> LoadEntitiesFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        ///  基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体集合</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 基本查询方法,获取一个被AutoMapper映射后的集合,优先从二级缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序字段</typeparam>
+        /// <typeparam name="TDto">输出类型</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序方式</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        Task<EFCachedQueryable<TDto>> LoadEntitiesFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntity<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntity<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntity<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCache(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromCache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCache<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2Cache(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        T GetFirstEntityFromL2Cache<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2Cache<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2Cache<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        ///  获取第一条数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(异步)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromCacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromCacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        T GetFirstEntityFromL2CacheNoTracking<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从二级缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        TDto GetFirstEntityFromL2CacheNoTracking<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync(Expression<Func<T, bool>> @where, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<T> GetFirstEntityFromCacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromCacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>实体</returns>
+        Task<T> GetFirstEntityFromL2CacheNoTrackingAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TDto>(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 获取第一条被AutoMapper映射后的数据,优先从缓存读取(异步,不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS">排序</typeparam>
+        /// <typeparam name="TDto">映射实体</typeparam>
+        /// <param name="where">查询条件</param>
+        /// <param name="orderby">排序字段</param>
+        /// <param name="isAsc">是否升序</param>
+        /// <returns>映射实体</returns>
+        Task<TDto> GetFirstEntityFromL2CacheNoTrackingAsync<TS, TDto>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID找实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        T GetById(object id);
+
+        /// <summary>
+        /// 根据ID找实体(异步)
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>实体</returns>
+        Task<T> GetByIdAsync(object id);
+
+        /// <summary>
+        /// 高效分页查询方法
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
+
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntities<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc, int timespan = 30);
+
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2Cache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2Cache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
+
+        /// <summary>
+        /// 高效分页查询方法(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<T> LoadPageEntitiesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IQueryable<TDto> LoadPageEntitiesNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromCacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <param name="timespan">缓存过期时间</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromCacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true, int timespan = 30) where TDto : class;
+
+        /// <summary>
+        /// 高效分页查询方法,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 高效分页查询方法,取出被AutoMapper映射后的数据集合,优先从缓存读取(不跟踪实体)
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="pageIndex">第几页</param>
+        /// <param name="pageSize">每页大小</param>
+        /// <param name="totalCount">数据总数</param>
+        /// <param name="where">where Lambda条件表达式</param>
+        /// <param name="orderby">orderby Lambda条件表达式</param>
+        /// <param name="isAsc">升序降序</param>
+        /// <returns>还未执行的SQL语句</returns>
+        IEnumerable<TDto> LoadPageEntitiesFromL2CacheNoTracking<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+
+        /// <summary>
+        /// 根据ID删除实体
+        /// </summary>
+        /// <param name="id">实体id</param>
+        /// <returns>删除成功</returns>
+        bool DeleteById(object id);
+
+        /// <summary>
+        /// 删除实体
+        /// </summary>
+        /// <param name="t">需要删除的实体</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntity(T t);
+
+        /// <summary>
+        /// 根据条件删除实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        int DeleteEntity(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 根据条件删除实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>删除成功</returns>
+        Task<int> DeleteEntityAsync(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 更新实体
+        /// </summary>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntity(T t);
+
+        /// <summary>
+        /// 根据条件更新实体
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        int UpdateEntity(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 根据条件更新实体(异步)
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <param name="t">更新后的实体</param>
+        /// <returns>更新成功</returns>
+        Task<int> UpdateEntityAsync(Expression<Func<T, bool>> @where, T t);
+
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        T AddEntity(T t);
+
+        /// <summary>
+        /// 批量添加实体
+        /// </summary>
+        /// <param name="list">需要添加的实体</param>
+        void BulkInsert(IEnumerable<T> list);
+
+        /// <summary>
+        /// 添加或更新
+        /// </summary>
+        /// <param name="exp">更新条件</param>
+        /// <param name="entities">实体集合</param>
+        void AddOrUpdate(Expression<Func<T, object>> exp, params T[] entities);
+
+        /// <summary>
+        /// 统一保存数据
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        int SaveChanges();
+
+        /// <summary>
+        /// 统一批量保存数据
+        /// </summary>
+        void BulkSaveChanges();
+
+        /// <summary>
+        /// 统一保存数据(异步)
+        /// </summary>
+        /// <returns>受影响的行数</returns>
+        Task<int> SaveChangesAsync();
+
+        /// <summary>
+        /// 判断实体是否在数据库中存在
+        /// </summary>
+        /// <param name="where">查询条件</param>
+        /// <returns>是否存在</returns>
+        bool Any(Expression<Func<T, bool>> @where);
+
+        /// <summary>
+        /// 删除多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>删除成功</returns>
+        bool DeleteEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 更新多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>更新成功</returns>
+        bool UpdateEntities(IEnumerable<T> list);
+
+        /// <summary>
+        /// 添加多个实体
+        /// </summary>
+        /// <param name="list">实体集合</param>
+        /// <returns>添加成功</returns>
+        IEnumerable<T> AddEntities(IList<T> list);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="TS"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        /// <returns>泛型集合</returns>
+        DbRawSqlQuery<TS> SqlQuery<TS>(string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行查询语句
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="sql"></param>
+        /// <param name="parameters">参数</param>
+        DbRawSqlQuery SqlQuery(Type t, string sql, params SqlParameter[] parameters);
+
+        /// <summary>
+        /// 执行DML语句
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="parameters"></param>
+        void ExecuteSql(string sql, params SqlParameter[] parameters);
+    }
+
+<#
+foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
+{#>	
+	public partial interface I<#=entity.Name#>Dal :IBaseDal<<#=entity.Name#>>{}
+<#}#>	
+}

+ 77 - 0
src/IDAL/IDAL.csproj

@@ -0,0 +1,77 @@
+<?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>{7997FB01-C9C1-4793-A430-9CA3C3852B37}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>IDAL</RootNamespace>
+    <AssemblyName>IDAL</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="EFSecondLevelCache, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\EFSecondLevelCache.1.2.0.0\lib\net45\EFSecondLevelCache.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.ComponentModel.DataAnnotations" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="IBaseDal.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>IBaseDal.tt</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="IBaseDal.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>IBaseDal.cs</LastGenOutput>
+    </Content>
+    <Content Include="readme.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Models\Models.csproj">
+      <Project>{5400ca01-cbcf-4531-a388-3057393d5b4f}</Project>
+      <Name>Models</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 36 - 0
src/IDAL/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("IDAL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("IDAL")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("7997fb01-c9c1-4793-a430-9ca3c3852b37")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 5 - 0
src/IDAL/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
+  <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
+</packages>

+ 70 - 0
src/IDAL/readme.txt

@@ -0,0 +1,70 @@
+EFSecondLevelCache
+=======
+Entity Framework 6.x Second Level Caching Library.
+
+Second level caching is a query cache. The results of EF commands will be stored in the cache,
+so that the same EF commands will retrieve their data from the cache rather than executing them
+against the database again.
+
+
+Usage:
+1- Setting up the cache invalidation by overriding the SaveChanges method to prevent stale reads:
+
+namespace EFSecondLevelCache.TestDataLayer.DataLayer
+{
+	public class SampleContext : DbContext
+	{
+		// public DbSet<Product> Products { get; set; }
+
+		public SampleContext()
+			: base("connectionString1")
+		{
+		}
+
+		public override int SaveChanges()
+		{
+			return SaveAllChanges(invalidateCacheDependencies: true);
+		}
+
+		public int SaveAllChanges(bool invalidateCacheDependencies = true)
+		{
+			var changedEntityNames = getChangedEntityNames();
+			var result = base.SaveChanges();
+			if (invalidateCacheDependencies)
+			{
+				new EFCacheServiceProvider().InvalidateCacheDependencies(changedEntityNames);
+			}
+			return result;
+		}
+
+		private string[] getChangedEntityNames()
+		{
+			// Updated version of this method: \EFSecondLevelCache\EFSecondLevelCache.Tests\EFSecondLevelCache.TestDataLayer\DataLayer\SampleContext.cs
+			return this.ChangeTracker.Entries()
+				.Where(x => x.State == EntityState.Added ||
+							x.State == EntityState.Modified ||
+							x.State == EntityState.Deleted)
+				.Select(x => System.Data.Entity.Core.Objects.ObjectContext.GetObjectType(x.Entity.GetType()).FullName)
+				.Distinct()
+				.ToArray();
+		}
+	}
+}
+
+Sometimes you don't want to invalidate the cache when non important properties such as NumberOfViews are updated.
+In these cases, try SaveAllChanges(invalidateCacheDependencies: false), before updating the data.
+
+2- Then to cache the results of the normal queries like:
+var products = context.Products.Include(x => x.Tags).FirstOrDefault();
+
+We can use the new `Cacheable()` extension method:
+var products = context.Products.Include(x => x.Tags).Cacheable().FirstOrDefault(); // Async methods are supported too.
+
+
+Notes:
+Good candidates for query caching are global site's settings, list of public articles or comments
+and not frequently changed, private or specific data to each user.
+If a page requires authentication, its data shouldn't be cached.
+
+Project's Url:
+https://github.com/VahidN/EFSecondLevelCache

文件差异内容过多而无法显示
+ 0 - 0
src/Masuit.MyBlogs.WebApp/App_Data/ban.txt


+ 181 - 0
src/Masuit.MyBlogs.WebApp/App_Data/config.json

@@ -0,0 +1,181 @@
+/* 前后端通信相关的配置,注释只允许使用多行方式 */
+{
+    /* 上传图片配置项 */
+    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
+    "imageFieldName": "upfile", /* 提交的图片表单名称 */
+    "imageMaxSize": 20480000, /* 上传大小限制,单位B */
+    "imageAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp",".ico","webp" ], /* 上传图片格式显示 */
+    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
+    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
+    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
+    "imageUrlPrefix": "", /* 图片访问路径前缀 */
+    "imagePathFormat": "/upload/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
+    /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
+    /* {time} 会替换成时间戳 */
+    /* {yyyy} 会替换成四位年份 */
+    /* {yy} 会替换成两位年份 */
+    /* {mm} 会替换成两位月份 */
+    /* {dd} 会替换成两位日期 */
+    /* {hh} 会替换成两位小时 */
+    /* {ii} 会替换成两位分钟 */
+    /* {ss} 会替换成两位秒 */
+    /* 非法字符 \ : * ? " < > | */
+    /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
+
+    /* 涂鸦图片上传配置项 */
+    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
+    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
+    "scrawlPathFormat": "/upload/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "scrawlMaxSize": 20480000, /* 上传大小限制,单位B */
+    "scrawlUrlPrefix": "", /* 图片访问路径前缀 */
+    "scrawlInsertAlign": "none",
+
+    /* 截图工具上传 */
+    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
+    "snapscreenPathFormat": "/upload/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
+    "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
+
+    /* 抓取远程图片配置 */
+    "catcherLocalDomain": [ "127.0.0.1", "localhost", "img.baidu.com" ],
+    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
+    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
+    "catcherPathFormat": "/upload/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "catcherUrlPrefix": "", /* 图片访问路径前缀 */
+    "catcherMaxSize": 20480000, /* 上传大小限制,单位B */
+    "catcherAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp" ], /* 抓取图片格式显示 */
+
+    /* 上传视频配置 */
+    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
+    "videoFieldName": "upfile", /* 提交的视频表单名称 */
+    "videoPathFormat": "upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "videoUrlPrefix": "", /* 视频访问路径前缀 */
+    "videoMaxSize": 2147483647, /* 上传大小限制,单位B,默认100MB */
+    "videoAllowFiles": [
+        ".flv",
+        ".f4v",
+        ".swf",
+        ".mkv",
+        ".avi",
+        ".rm",
+        ".rmvb",
+        ".mpeg",
+        ".mpg",
+        ".ogg",
+        ".ogv",
+        ".mov",
+        ".wmv",
+        ".mp4",
+        ".webm",
+        ".mp3",
+        ".wav",
+        ".mid"
+    ], /* 上传视频格式显示 */
+
+    /* 上传文件配置 */
+    "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
+    "fileFieldName": "upfile", /* 提交的文件表单名称 */
+    "filePathFormat": "upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "fileUrlPrefix": "", /* 文件访问路径前缀 */
+    "fileMaxSize": 2147483647, /* 上传大小限制,单位B,默认50MB */
+    "fileAllowFiles": [
+        ".png",
+        ".jpg",
+        ".jpeg",
+        ".gif",
+        ".bmp",
+        ".flv",
+        ".swf",
+        ".mkv",
+        ".avi",
+        ".rm",
+        ".rmvb",
+        ".mpeg",
+        ".mpg",
+        ".ogg",
+        ".ogv",
+        ".mov",
+        ".wmv",
+        ".mp4",
+        ".webm",
+        ".mp3",
+        ".wav",
+        ".mid",
+        ".rar",
+        ".zip",
+        ".tar",
+        ".gz",
+        ".7z",
+        ".bz2",
+        ".cab",
+        ".iso",
+        ".doc",
+        ".docx",
+        ".xls",
+        ".xlsx",
+        ".ppt",
+        ".pptx",
+        ".pdf",
+        ".txt",
+        ".md",
+        ".xml"
+    ], /* 上传文件格式显示 */
+
+    /* 列出指定目录下的图片 */
+    "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
+    "imageManagerListPath": "/upload/images", /* 指定要列出图片的目录 */
+    "imageManagerListSize": 20, /* 每次列出文件数量 */
+    "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
+    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
+    "imageManagerAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp",".ico" ], /* 列出的文件类型 */
+
+    /* 列出指定目录下的文件 */
+    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
+    "fileManagerListPath": "upload/file", /* 指定要列出文件的目录 */
+    "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */
+    "fileManagerListSize": 20, /* 每次列出文件数量 */
+    "fileManagerAllowFiles": [
+        ".png",
+        ".jpg",
+        ".jpeg",
+        ".gif",
+        ".bmp",
+        ".flv",
+        ".swf",
+        ".mkv",
+        ".avi",
+        ".rm",
+        ".rmvb",
+        ".mpeg",
+        ".mpg",
+        ".ogg",
+        ".ogv",
+        ".mov",
+        ".wmv",
+        ".mp4",
+        ".webm",
+        ".mp3",
+        ".wav",
+        ".mid",
+        ".rar",
+        ".zip",
+        ".tar",
+        ".gz",
+        ".7z",
+        ".bz2",
+        ".cab",
+        ".iso",
+        ".doc",
+        ".docx",
+        ".xls",
+        ".xlsx",
+        ".ppt",
+        ".pptx",
+        ".pdf",
+        ".txt",
+        ".md",
+        ".xml"
+    ] /* 列出的文件类型 */
+
+}

+ 1 - 0
src/Masuit.MyBlogs.WebApp/App_Data/denyip.txt

@@ -0,0 +1 @@
+220.181.158.218,220.181.55.144

文件差异内容过多而无法显示
+ 0 - 0
src/Masuit.MyBlogs.WebApp/App_Data/mod.txt


+ 52 - 0
src/Masuit.MyBlogs.WebApp/App_Start/AutofacConfig.cs

@@ -0,0 +1,52 @@
+using System.Reflection;
+using System.Web.Mvc;
+using Autofac;
+using Autofac.Integration.Mvc;
+using Autofac.Integration.WebApi;
+using Common;
+using Hangfire;
+using Masuit.MyBlogs.WebApp.Models.Hangfire;
+using Masuit.Tools.NoSQL;
+using Microsoft.AspNet.SignalR;
+using Models.Application;
+using GlobalConfiguration = System.Web.Http.GlobalConfiguration;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    /// <summary>
+    /// autofac配置类
+    /// </summary>
+    public class AutofacConfig
+    {
+        public static IContainer Container { get; set; }
+        /// <summary>
+        /// 负责调用autofac实现依赖注入,负责创建MVC控制器类的对象(调用控制器的有参构造函数),接管DefaultControllerFactory的工作
+        /// </summary>
+        public static void RegisterMVC()
+        {
+            //1.0 实例化autofac的创建容器
+            var builder = new ContainerBuilder();
+
+            //2.0 告诉autofac将来要创建的控制器类存放在哪个程序集
+            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired(PropertyWiringOptions.PreserveSetValues);
+            builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
+            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
+            builder.RegisterFilterProvider();
+
+            //3.0 告诉autofac注册所有的Bll,创建类的实例,以该类的接口实现实例存储
+            builder.RegisterType<DataContext>().OnRelease(db => db.Dispose()).InstancePerLifetimeScope();
+            builder.RegisterAssemblyTypes(Assemblies.RepositoryAssembly).AsSelf().AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();
+            builder.RegisterAssemblyTypes(Assemblies.ServiceAssembly).AsSelf().AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();
+            builder.RegisterType<RedisHelper>().OnRelease(db => db.Dispose()).InstancePerLifetimeScope();
+            builder.RegisterType<BackgroundJobClient>().SingleInstance();//指定生命周期为单例
+            builder.RegisterType<HangfireBackJob>().As<IHangfireBackJob>().PropertiesAutowired(PropertyWiringOptions.PreserveSetValues).InstancePerDependency();
+            //4.0 创建一个autofac的容器
+            Container = builder.Build();
+
+            //5.0 将当前容器交给MVC底层,保证容器不被销毁,控制器由autofac来创建
+            GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(Container);
+            GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(Container);
+            DependencyResolver.SetResolver(new AutofacDependencyResolver(Container));
+        }
+    }
+}

+ 65 - 0
src/Masuit.MyBlogs.WebApp/App_Start/BundleConfig.cs

@@ -0,0 +1,65 @@
+using System.Web.Optimization;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    public class BundleConfig
+    {
+        public static void RegisterBundles(BundleCollection bundles)
+        {
+            //javascript脚本
+            bundles.Add(new ScriptBundle("~/js").Include(
+                "~/Scripts/bootstrap-suggest.min.js",
+                "~/Scripts/jquery.query.js",
+                "~/Scripts/jquery.paging.js",
+                "~/Scripts/ripplet.js",
+                "~/Assets/tippy/tippy.js",
+                "~/Scripts/global/scripts.js"
+                ));
+
+            bundles.Add(new ScriptBundle("~/bundles").Include(
+                 "~/Assets/newsbox/jquery.bootstrap.newsbox.js",
+                 "~/Assets/tab/stopExecutionOnTimeout.js",
+                 "~/Assets/tab/init.js",
+                 //"~/Assets/modal/custombox.js",
+                 "~/Assets/tagcloud/js/tagcloud.js",
+                 "~/Assets/scrolltop/js/scrolltop.js",
+                "~/Assets/nav/js/main.js"
+                ));
+
+            bundles.Add(new ScriptBundle("~/ng-views/filemgr").Include(
+                 "~/ng-views/filemanager/js/app.js",
+                 "~/ng-views/filemanager/js/directives/directives.js",
+                 "~/ng-views/filemanager/js/filters/filters.js",
+                 "~/ng-views/filemanager/js/providers/config.js",
+                 "~/ng-views/filemanager/js/entities/chmod.js",
+                 "~/ng-views/filemanager/js/entities/item.js",
+                 "~/ng-views/filemanager/js/services/apihandler.js",
+                 "~/ng-views/filemanager/js/services/apimiddleware.js",
+                 "~/ng-views/filemanager/js/services/filenavigator.js",
+                 "~/ng-views/filemanager/js/providers/translations.js",
+                 "~/ng-views/filemanager/js/controllers/main.js",
+                 "~/ng-views/filemanager/js/controllers/selector-controller.js"
+                ));
+
+            //css样式
+            bundles.Add(new StyleBundle("~/css").Include(
+                "~/Content/jquery.paging.css",
+                "~/Content/common/reset.css",
+                "~/Content/common/loading.css",
+                "~/Content/common/style.css",
+                "~/Content/common/articlestyle.css",
+                "~/Content/common/leaderboard.css",
+                "~/Content/microtip.min.css"
+                ));
+            bundles.Add(new StyleBundle("~/styles").Include(
+                "~/Assets/breadcrumb/style.css",
+                "~/Assets/nav/css/style.css",
+                //"~/Assets/modal/custombox.css",
+                //"~/Assets/modal/demo.css",
+                "~/Assets/tab/styles.css",
+                "~/Assets/tagcloud/css/tagcloud.css",
+                "~/Assets/tippy/tippy.css"
+                ));
+        }
+    }
+}

+ 79 - 0
src/Masuit.MyBlogs.WebApp/App_Start/CollectRunningInfo.cs

@@ -0,0 +1,79 @@
+using System;
+using System.Threading;
+using Hangfire;
+using Masuit.MyBlogs.WebApp.Hubs;
+using Masuit.Tools.DateTimeExt;
+using Masuit.Tools.Hardware;
+using Masuit.Tools.Logging;
+using Masuit.Tools.Win32;
+using static Common.CommonHelper;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    /// <summary>
+    /// 收集系统运行状态
+    /// </summary>
+    public class CollectRunningInfo
+    {
+        public static void Start()
+        {
+            MyHub.PushData(a =>
+            {
+                try
+                {
+                    double time = DateTime.Now.GetTotalMilliseconds();// - 28800000;
+                    float load = SystemInfo.CpuLoad;
+                    double temperature = SystemInfo.GetCPUTemperature();
+                    double mem = (1 - SystemInfo.MemoryAvailable.To<double>() / SystemInfo.PhysicalMemory.To<double>()) * 100;
+                    a.receiveLoad($"[{time},{load},{mem},{temperature}]");//CPU
+
+                    var read = SystemInfo.GetDiskData(DiskData.Read) / 1024;
+                    var write = SystemInfo.GetDiskData(DiskData.Write) / 1024;
+                    a.receiveReadWrite($"[{time},{read},{write}]");//磁盘IO
+
+                    var up = SystemInfo.GetNetData(NetData.Received) / 1024;
+                    var down = SystemInfo.GetNetData(NetData.Sent) / 1024;
+                    a.receiveUpDown($"[{time},{down},{up}]");//网络上下载
+
+                    if (mem > 90)
+                    {
+                        mem = Windows.ClearMemory();
+                        Thread.Sleep(2000);
+                    }
+                    if (mem > 90)
+                    {
+                        BackgroundJob.Enqueue(() => SendMail("网站服务器负载过大预警!", "网站服务器负载过大,内存使用率已经超过90%,请及时检查服务器,避免网站被终止运行", GetSettings("ReceiveEmail")));
+                    }
+                    //缓存历史数据
+                    if (HistoryCpuLoad.Count < 50 || (time / 10000).ToInt32() % 12 == 0)
+                    {
+                        HistoryCpuLoad.Add(new object[] { time, load });
+                        HistoryCpuTemp.Add(new object[] { time, temperature });
+                        HistoryMemoryUsage.Add(new object[] { time, mem });
+                        HistoryIORead.Add(new object[] { time, read });
+                        HistoryIOWrite.Add(new object[] { time, write });
+                        HistoryNetReceive.Add(new object[] { time, up });
+                        HistoryNetSend.Add(new object[] { time, down });
+                        if (HistoryCpuLoad.Count > 720)
+                        {
+                            HistoryCpuLoad.RemoveAt(0);
+                            HistoryMemoryUsage.RemoveAt(0);
+                            HistoryCpuTemp.RemoveAt(0);
+                        }
+                        if (HistoryIORead.Count > 720)
+                        {
+                            HistoryIORead.RemoveAt(0);
+                            HistoryIOWrite.RemoveAt(0);
+                            HistoryNetReceive.RemoveAt(0);
+                            HistoryNetSend.RemoveAt(0);
+                        }
+                    }
+                }
+                catch (Exception e)
+                {
+                    LogManager.Error(e);
+                }
+            });
+        }
+    }
+}

+ 20 - 0
src/Masuit.MyBlogs.WebApp/App_Start/FilterConfig.cs

@@ -0,0 +1,20 @@
+using System.Web.Mvc;
+using Masuit.MyBlogs.WebApp.Models;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    public class FilterConfig
+    {
+        /// <summary>
+        /// 注册全局的过滤器
+        /// </summary>
+        /// <param name="filters"></param>
+        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
+        {
+            filters.Add(new HandleErrorAttribute());
+            filters.Add(new MyActionFilterAttribute());
+            filters.Add(new MyExceptionFilterAttribute());
+            //filters.Add(new WhitespaceFilterAttribute());
+        }
+    }
+}

+ 141 - 0
src/Masuit.MyBlogs.WebApp/App_Start/HangfireConfig.cs

@@ -0,0 +1,141 @@
+using System;
+using System.Configuration;
+using System.Data.Entity;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using Common;
+using Hangfire;
+using Hangfire.Console;
+using Masuit.MyBlogs.WebApp.Models.Hangfire;
+using Masuit.Tools;
+using Masuit.Tools.NoSQL;
+using Masuit.Tools.Win32;
+using Models.Application;
+using Models.Enum;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    /// <summary>
+    /// hangfire配置
+    /// </summary>
+    public class HangfireConfig
+    {
+        public static void Register()
+        {
+            #region Hangfire配置
+
+            //GlobalConfiguration.Configuration.UseMemoryStorage();
+            GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["DataContext"].ConnectionString).UseConsole();
+            #region 实现类注册
+
+            GlobalConfiguration.Configuration.UseAutofacActivator(AutofacConfig.Container);
+
+            #endregion
+
+            #region 服务启动
+
+            Server = new BackgroundJobServer(new BackgroundJobServerOptions
+            {
+                ServerName = $"{Environment.MachineName}", //服务器名称
+                SchedulePollingInterval = TimeSpan.FromSeconds(1),
+                ServerCheckInterval = TimeSpan.FromSeconds(1),
+                WorkerCount = Environment.ProcessorCount * 2,
+                //Queues = new[] { "masuit" } //队列名
+            });
+            #endregion
+
+            #endregion
+            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));//更新文章索引
+            AggregateInterviews();//访客统计
+            RecurringJob.AddOrUpdate(() => Windows.ClearMemorySilent(), Cron.Hourly);//每小时清理系统内存
+            RecurringJob.AddOrUpdate(() => CheckLinks(), Cron.HourInterval(5));//每5h检查友链
+            RecurringJob.AddOrUpdate(() => EverydayJob(), Cron.Daily, TimeZoneInfo.Local);//每天的任务
+            RecurringJob.AddOrUpdate(() => FlushAddress(), Cron.Weekly(DayOfWeek.Sunday, 2), TimeZoneInfo.Local);//刷新没统计到的访客的信息
+            RecurringJob.AddOrUpdate(() => AggregateInterviews(), Cron.Hourly(30));//每半小时统计访客
+            using (RedisHelper redisHelper = RedisHelper.GetInstance())
+            {
+                if (!redisHelper.KeyExists("ArticleViewToken"))
+                {
+                    redisHelper.SetString("ArticleViewToken", string.Empty.CreateShortToken());//更新加密文章的密码
+                }
+            }
+        }
+
+        public static BackgroundJobServer Server { get; set; }
+
+        /// <summary>
+        /// 刷新没统计到的访客的信息
+        /// </summary>
+        public static void FlushAddress()
+        {
+            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.FlushUnhandledAddress));
+        }
+
+        /// <summary>
+        /// 每天的任务
+        /// </summary>
+        public static void EverydayJob()
+        {
+            CommonHelper.IPErrorTimes.RemoveWhere(kv => kv.Value < 100);//将访客访问出错次数少于100的移开
+            using (RedisHelper redisHelper = RedisHelper.GetInstance())
+            {
+                redisHelper.SetString("ArticleViewToken", string.Empty.CreateShortToken());//更新加密文章的密码
+            }
+            using (DataContext db = new DataContext())
+            {//清理hangfire数据库
+                db.Database.ExecuteSqlCommand(@"DELETE FROM [HangFire].[Job] WHERE StateName='Succeeded' or StateName='Deleted';
+                    TRUNCATE TABLE [HangFire].[Counter];
+                    DELETE FROM [HangFire].[Hash] WHERE Field='Jobid';
+                    DELETE FROM [HangFire].[AggregatedCounter] WHERE ExpireAt is not null;
+                    UPDATE [HangFire].[AggregatedCounter] SET [Value] = (select count(1) from [HangFire].[Job] WHERE StateName<>'Succeeded' and StateName<>'Deleted')-1 WHERE [Key] = 'stats:succeeded'; 
+                    UPDATE [HangFire].[AggregatedCounter] SET [Value] = 0 WHERE [Key] = 'stats:deleted'");
+            }
+        }
+
+        public static void AggregateInterviews()
+        {
+            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.AggregateInterviews));
+        }
+
+        /// <summary>
+        /// 检查友链
+        /// </summary>
+        public static void CheckLinks()
+        {
+            using (DataContext db = new DataContext())
+            {
+                var links = db.Links.Where(l => !l.Except).AsParallel();
+                Parallel.ForEach(links, link =>
+                 {
+                     Uri uri = new Uri(link.Url);
+                     using (HttpClient client = new HttpClient() { BaseAddress = uri })
+                     {
+                         client.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
+                         client.DefaultRequestHeaders.Referrer = new Uri("https://masuit.com");
+                         client.GetAsync(uri.PathAndQuery).ContinueWith(async t =>
+                         {
+                             if (t.IsCanceled || t.IsFaulted)
+                             {
+                                 link.Status = Status.Unavailable;
+                                 return;
+                             }
+                             var res = await t;
+                             if (res.IsSuccessStatusCode)
+                             {
+                                 link.Status = !(await res.Content.ReadAsStringAsync()).Contains(CommonHelper.GetSettings("Domain")) ? Status.Unavailable : Status.Available;
+                             }
+                             else
+                             {
+                                 link.Status = Status.Unavailable;
+                             }
+                             db.Entry(link).State = EntityState.Modified;
+                         }).Wait();
+                     }
+                 });
+                db.SaveChanges();
+            }
+        }
+    }
+}

+ 26 - 0
src/Masuit.MyBlogs.WebApp/App_Start/RouteConfig.cs

@@ -0,0 +1,26 @@
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    public class RouteConfig
+    {
+        public static void RegisterRoutes(RouteCollection routes)
+        {
+            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+            routes.IgnoreRoute("{resource}.ashx");
+            routes.MapMvcAttributeRoutes();
+            routes.MapRoute(
+                name: "Default",
+                url: "{controller}/{action}/{id}",
+                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
+            );
+            routes.MapRoute(
+                name: "page2",
+                url: "{controller}/{action}/{page}/{size}/{orderby}",
+                defaults: new { controller = "Home", action = "Post", page = UrlParameter.Optional, size = UrlParameter.Optional, orderby = UrlParameter.Optional }
+            );
+        }
+    }
+}
+

+ 25 - 0
src/Masuit.MyBlogs.WebApp/App_Start/StartupConfig.cs

@@ -0,0 +1,25 @@
+using System.Web.Mvc;
+using Common;
+using FluentScheduler;
+using Models.Application;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    /// <summary>
+    /// 网站启动配置
+    /// </summary>
+    public class StartupConfig
+    {
+        public static void Startup()
+        {
+            //移除aspx视图引擎
+            ViewEngines.Engines.RemoveAt(0);
+            RegisterAutomapper.Excute();
+            using (new DataContext()) { }
+            HangfireConfig.Register();
+            Registry reg = new Registry();
+            reg.Schedule(() => CollectRunningInfo.Start()).ToRunNow().AndEvery(5).Seconds();//启动服务器监控任务
+            JobManager.Initialize(reg);//初始化定时器
+        }
+    }
+}

+ 260 - 0
src/Masuit.MyBlogs.WebApp/App_Start/SwaggerConfig.cs

@@ -0,0 +1,260 @@
+using System;
+using System.IO;
+using System.Web.Http;
+using Masuit.MyBlogs.WebApp;
+using Swashbuckle.Application;
+using WebActivatorEx;
+
+[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
+
+namespace Masuit.MyBlogs.WebApp
+{
+    public class SwaggerConfig
+    {
+        public static void Register()
+        {
+            var thisAssembly = typeof(SwaggerConfig).Assembly;
+
+            GlobalConfiguration.Configuration
+                .EnableSwagger(c =>
+                    {
+                        // By default, the service root url is inferred from the request used to access the docs.
+                        // However, there may be situations (e.g. proxy and load-balanced environments) where this does not
+                        // resolve correctly. You can workaround this by providing your own code to determine the root URL.
+                        //
+                        //c.RootUrl(req => GetRootUrlFromAppConfig());
+
+                        // If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
+                        // the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
+                        // about them, you can use the "Schemes" option as shown below.
+                        //
+                        //c.Schemes(new[] { "http", "https" });
+
+                        // Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
+                        // hold additional metadata for an API. Version and title are required but you can also provide
+                        // additional fields by chaining methods off SingleApiVersion.
+                        //
+                        c.SingleApiVersion("v1", "²©¿Í¿ª·Åƽ̨");
+
+                        // If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
+                        //
+                        //c.PrettyPrint();
+
+                        // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
+                        // In this case, you must provide a lambda that tells Swashbuckle which actions should be
+                        // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
+                        // returns an "Info" builder so you can provide additional metadata per API version.
+                        //
+                        //c.MultipleApiVersions(
+                        //    (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
+                        //    (vc) =>
+                        //    {
+                        //        vc.Version("v2", "Swashbuckle Dummy API V2");
+                        //        vc.Version("v1", "Swashbuckle Dummy API V1");
+                        //    });
+
+                        // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
+                        // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
+                        // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
+                        // at the document or operation level to indicate which schemes are required for an operation. To do this,
+                        // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
+                        // according to your specific authorization implementation
+                        //
+                        //c.BasicAuth("basic")
+                        //    .Description("Basic HTTP Authentication");
+                        //
+                        // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
+                        c.ApiKey("apiKey")
+                            .Description("API Key Authentication")
+                            .Name("apiKey")
+                            .In("header");
+
+                        //c.OAuth2("oauth2")
+                        //    .Description("OAuth2 Implicit Grant")
+                        //    .Flow("implicit")
+                        //    .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
+                        //    //.TokenUrl("https://tempuri.org/token")
+                        //    .Scopes(scopes =>
+                        //    {
+                        //        scopes.Add("read", "Read access to protected resources");
+                        //        scopes.Add("write", "Write access to protected resources");
+                        //    });
+
+                        // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
+                        //c.IgnoreObsoleteActions();
+
+                        // Each operation be assigned one or more tags which are then used by consumers for various reasons.
+                        // For example, the swagger-ui groups operations according to the first tag of each operation.
+                        // By default, this will be controller name but you can use the "GroupActionsBy" option to
+                        // override with any value.
+                        //
+                        //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
+
+                        // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
+                        // the order in which operations are listed. For example, if the default grouping is in place
+                        // (controller name) and you specify a descending alphabetic sort order, then actions from a
+                        // ProductsController will be listed before those from a CustomersController. This is typically
+                        // used to customize the order of groupings in the swagger-ui.
+                        //
+                        //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
+
+                        // If you annotate Controllers and API Types with
+                        // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
+                        // those comments into the generated docs and UI. You can enable this by providing the path to one or
+                        // more Xml comment files.
+                        //
+                        //c.IncludeXmlComments(GetXmlCommentsPath());
+                        c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "Masuit.MyBlogs.WebApp.xml"));
+                        c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "Models.xml"));
+                        c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "Masuit.Tools.xml"));
+
+                        // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
+                        // exposed in your API. However, there may be occasions when more control of the output is needed.
+                        // This is supported through the "MapType" and "SchemaFilter" options:
+                        //
+                        // Use the "MapType" option to override the Schema generation for a specific type.
+                        // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
+                        // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
+                        // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
+                        // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
+                        // complex Schema, use a Schema filter.
+                        //
+                        //c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
+
+                        // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
+                        // specific type, you can wire up one or more Schema filters.
+                        //
+                        //c.SchemaFilter<ApplySchemaVendorExtensions>();
+
+                        // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
+                        // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
+                        // works well because it prevents the "implementation detail" of type namespaces from leaking into your
+                        // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
+                        // need to opt out of this behavior to avoid Schema Id conflicts.
+                        //
+                        //c.UseFullTypeNameInSchemaIds();
+
+                        // Alternatively, you can provide your own custom strategy for inferring SchemaId's for
+                        // describing "complex" types in your API.
+                        //
+                        //c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
+
+                        // Set this flag to omit schema property descriptions for any type properties decorated with the
+                        // Obsolete attribute
+                        c.IgnoreObsoleteProperties();
+
+                        // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
+                        // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
+                        // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
+                        // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
+                        //
+                        //c.DescribeAllEnumsAsStrings();
+
+                        // Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
+                        //
+                        // Post-modify Operation descriptions once they've been generated by wiring up one or more
+                        // Operation filters.
+                        //
+                        //c.OperationFilter<AddDefaultResponse>();
+                        //
+                        // If you've defined an OAuth2 flow as described above, you could use a custom filter
+                        // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
+                        // to execute the operation
+                        //
+                        //c.OperationFilter<AssignOAuth2SecurityRequirements>();
+
+                        // Post-modify the entire Swagger document by wiring up one or more Document filters.
+                        // This gives full control to modify the final SwaggerDocument. You should have a good understanding of
+                        // the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
+                        // before using this option.
+                        //
+                        //c.DocumentFilter<ApplyDocumentVendorExtensions>();
+
+                        // In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
+                        // to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
+                        // with the same path (sans query string) and HTTP method. You can workaround this by providing a
+                        // custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
+                        //
+                        //c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
+
+                        // Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
+                        // alternative implementation for ISwaggerProvider with the CustomProvider option.
+                        //
+                        //c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
+                    })
+                .EnableSwaggerUi(c =>
+                    {
+                        // Use the "DocumentTitle" option to change the Document title.
+                        // Very helpful when you have multiple Swagger pages open, to tell them apart.
+                        //
+                        //c.DocumentTitle("My Swagger UI");
+
+                        // Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
+                        // The file must be included in your project as an "Embedded Resource", and then the resource's
+                        // "Logical Name" is passed to the method as shown below.
+                        //
+                        //c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
+
+                        // Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
+                        // has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
+                        // "Logical Name" is passed to the method as shown above.
+                        //
+                        //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
+
+                        // The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
+                        // strings as the possible choices. You can use this option to change these to something else,
+                        // for example 0 and 1.
+                        //
+                        //c.BooleanValues(new[] { "0", "1" });
+
+                        // By default, swagger-ui will validate specs against swagger.io's online validator and display the result
+                        // in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
+                        // feature entirely.
+                        //c.SetValidatorUrl("http://localhost/validator");
+                        //c.DisableValidator();
+
+                        // Use this option to control how the Operation listing is displayed.
+                        // It can be set to "None" (default), "List" (shows operations for each resource),
+                        // or "Full" (fully expanded: shows operations and their details).
+                        //
+                        //c.DocExpansion(DocExpansion.List);
+
+                        // Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
+                        // it for all operations.
+                        //
+                        //c.SupportedSubmitMethods("GET", "HEAD");
+
+                        // Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
+                        // It's typically used to instruct Swashbuckle to return your version instead of the default
+                        // when a request is made for "index.html". As with all custom content, the file must be included
+                        // in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
+                        // the method as shown below.
+                        //
+                        //c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
+
+                        // If your API has multiple versions and you've applied the MultipleApiVersions setting
+                        // as described above, you can also enable a select box in the swagger-ui, that displays
+                        // a discovery URL for each version. This provides a convenient way for users to browse documentation
+                        // for different API versions.
+                        //
+                        //c.EnableDiscoveryUrlSelector();
+
+                        // If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
+                        // the Swagger 2.0 specification, you can enable UI support as shown below.
+                        //
+                        //c.EnableOAuth2Support(
+                        //    clientId: "test-client-id",
+                        //    clientSecret: null,
+                        //    realm: "test-realm",
+                        //    appName: "Swagger UI"
+                        //    //additionalQueryStringParams: new Dictionary<string, string>() { { "foo", "bar" } }
+                        //);
+
+                        // If your API supports ApiKey, you can override the default values.
+                        // "apiKeyIn" can either be "query" or "header"
+                        //
+                        //c.EnableApiKeySupport("apiKey", "header");
+                    });
+        }
+    }
+}

+ 21 - 0
src/Masuit.MyBlogs.WebApp/App_Start/WebApiConfig.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web.Http;
+
+namespace Masuit.MyBlogs.WebApp
+{
+    public static class WebApiConfig
+    {
+        public static void Register(HttpConfiguration config)
+        {
+            config.MapHttpAttributeRoutes();
+
+            config.Routes.MapHttpRoute(
+                name: "DefaultApi",
+                routeTemplate: "api/{controller}/{id}",
+                defaults: new { id = RouteParameter.Optional }
+            );
+        }
+    }
+}

+ 40 - 0
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/anchor/anchor.html

@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+    "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+        <title></title>
+        <style type="text/css">
+            *{color: #838383;margin: 0;padding: 0}
+            html,body {font-size: 12px;overflow: hidden; }
+            .content{padding:5px 0 0 15px;}
+            input{width:210px;height:21px;line-height:21px;margin-left: 4px;}
+        </style>
+    </head>
+    <body>
+        <div class="content">
+            <span><var id="lang_input_anchorName"></var></span><input id="anchorName"  value="" />
+        </div>
+        <script type="text/javascript" src="../internal.js"></script>
+        <script type="text/javascript">
+            var anchorInput = $G('anchorName'),
+                node = editor.selection.getRange().getClosedNode();
+            if(node && node.tagName == 'IMG' && (node = node.getAttribute('anchorname'))){
+                anchorInput.value = node;
+            }
+            anchorInput.onkeydown = function(evt){
+                evt = evt || window.event;
+                if(evt.keyCode == 13){
+                    editor.execCommand('anchor', anchorInput.value);
+                    dialog.close();
+                    domUtils.preventDefault(evt)
+                }
+            };
+            dialog.onok = function (){
+                editor.execCommand('anchor', anchorInput.value);
+                dialog.close();
+            };
+            $focus(anchorInput);
+        </script>
+    </body>
+</html>

+ 681 - 0
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/attachment.css

@@ -0,0 +1,681 @@
+@charset "utf-8";
+/* dialog样式 */
+.wrapper {
+    zoom: 1;
+    width: 630px;
+    *width: 626px;
+    height: 380px;
+    margin: 0 auto;
+    padding: 10px;
+    position: relative;
+    font-family: sans-serif;
+}
+
+/*tab样式框大小*/
+.tabhead {
+    float:left;
+}
+.tabbody {
+    width: 100%;
+    height: 346px;
+    position: relative;
+    clear: both;
+}
+
+.tabbody .panel {
+    position: absolute;
+    width: 0;
+    height: 0;
+    background: #fff;
+    overflow: hidden;
+    display: none;
+}
+
+.tabbody .panel.focus {
+    width: 100%;
+    height: 346px;
+    display: block;
+}
+
+/* 上传附件 */
+.tabbody #upload.panel {
+    width: 0;
+    height: 0;
+    overflow: hidden;
+    position: absolute !important;
+    clip: rect(1px, 1px, 1px, 1px);
+    background: #fff;
+    display: block;
+}
+
+.tabbody #upload.panel.focus {
+    width: 100%;
+    height: 346px;
+    display: block;
+    clip: auto;
+}
+
+#upload .queueList {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    overflow: hidden;
+}
+
+#upload p {
+    margin: 0;
+}
+
+.element-invisible {
+    width: 0 !important;
+    height: 0 !important;
+    border: 0;
+    padding: 0;
+    margin: 0;
+    overflow: hidden;
+    position: absolute !important;
+    clip: rect(1px, 1px, 1px, 1px);
+}
+
+#upload .placeholder {
+    margin: 10px;
+    border: 2px dashed #e6e6e6;
+    *border: 0px dashed #e6e6e6;
+    height: 172px;
+    padding-top: 150px;
+    text-align: center;
+    background: url(./images/image.png) center 70px no-repeat;
+    color: #cccccc;
+    font-size: 18px;
+    position: relative;
+    top:0;
+    *top: 10px;
+}
+
+#upload .placeholder .webuploader-pick {
+    font-size: 18px;
+    background: #00b7ee;
+    border-radius: 3px;
+    line-height: 44px;
+    padding: 0 30px;
+    *width: 120px;
+    color: #fff;
+    display: inline-block;
+    margin: 0 auto 20px auto;
+    cursor: pointer;
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+
+#upload .placeholder .webuploader-pick-hover {
+    background: #00a2d4;
+}
+
+
+#filePickerContainer {
+    text-align: center;
+}
+
+#upload .placeholder .flashTip {
+    color: #666666;
+    font-size: 12px;
+    position: absolute;
+    width: 100%;
+    text-align: center;
+    bottom: 20px;
+}
+
+#upload .placeholder .flashTip a {
+    color: #0785d1;
+    text-decoration: none;
+}
+
+#upload .placeholder .flashTip a:hover {
+    text-decoration: underline;
+}
+
+#upload .placeholder.webuploader-dnd-over {
+    border-color: #999999;
+}
+
+#upload .filelist {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+    height: 300px;
+}
+
+#upload .filelist:after {
+    content: '';
+    display: block;
+    width: 0;
+    height: 0;
+    overflow: hidden;
+    clear: both;
+}
+
+#upload .filelist li {
+    width: 113px;
+    height: 113px;
+    background: url(./images/bg.png);
+    text-align: center;
+    margin: 9px 0 0 9px;
+    *margin: 6px 0 0 6px;
+    position: relative;
+    display: block;
+    float: left;
+    overflow: hidden;
+    font-size: 12px;
+}
+
+#upload .filelist li p.log {
+    position: relative;
+    top: -45px;
+}
+
+#upload .filelist li p.title {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    top: 5px;
+    text-indent: 5px;
+    text-align: left;
+}
+
+#upload .filelist li p.progress {
+    position: absolute;
+    width: 100%;
+    bottom: 0;
+    left: 0;
+    height: 8px;
+    overflow: hidden;
+    z-index: 50;
+    margin: 0;
+    border-radius: 0;
+    background: none;
+    -webkit-box-shadow: 0 0 0;
+}
+
+#upload .filelist li p.progress span {
+    display: none;
+    overflow: hidden;
+    width: 0;
+    height: 100%;
+    background: #1483d8 url(./images/progress.png) repeat-x;
+
+    -webit-transition: width 200ms linear;
+    -moz-transition: width 200ms linear;
+    -o-transition: width 200ms linear;
+    -ms-transition: width 200ms linear;
+    transition: width 200ms linear;
+
+    -webkit-animation: progressmove 2s linear infinite;
+    -moz-animation: progressmove 2s linear infinite;
+    -o-animation: progressmove 2s linear infinite;
+    -ms-animation: progressmove 2s linear infinite;
+    animation: progressmove 2s linear infinite;
+
+    -webkit-transform: translateZ(0);
+}
+
+@-webkit-keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+@-moz-keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+@keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+#upload .filelist li p.imgWrap {
+    position: relative;
+    z-index: 2;
+    line-height: 113px;
+    vertical-align: middle;
+    overflow: hidden;
+    width: 113px;
+    height: 113px;
+
+    -webkit-transform-origin: 50% 50%;
+    -moz-transform-origin: 50% 50%;
+    -o-transform-origin: 50% 50%;
+    -ms-transform-origin: 50% 50%;
+    transform-origin: 50% 50%;
+
+    -webit-transition: 200ms ease-out;
+    -moz-transition: 200ms ease-out;
+    -o-transition: 200ms ease-out;
+    -ms-transition: 200ms ease-out;
+    transition: 200ms ease-out;
+}
+#upload .filelist li p.imgWrap.notimage {
+    margin-top: 0;
+    width: 111px;
+    height: 111px;
+    border: 1px #eeeeee solid;
+}
+#upload .filelist li p.imgWrap.notimage i.file-preview {
+    margin-top: 15px;
+}
+
+#upload .filelist li img {
+    width: 100%;
+}
+
+#upload .filelist li p.error {
+    background: #f43838;
+    color: #fff;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    height: 28px;
+    line-height: 28px;
+    width: 100%;
+    z-index: 100;
+    display:none;
+}
+
+#upload .filelist li .success {
+    display: block;
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    height: 40px;
+    width: 100%;
+    z-index: 200;
+    background: url(./images/success.png) no-repeat right bottom;
+    background-image: url(./images/success.gif) \9;
+}
+
+#upload .filelist li.filePickerBlock {
+    width: 113px;
+    height: 113px;
+    background: url(./images/image.png) no-repeat center 12px;
+    border: 1px solid #eeeeee;
+    border-radius: 0;
+}
+#upload .filelist li.filePickerBlock div.webuploader-pick  {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    opacity: 0;
+    background: none;
+    font-size: 0;
+}
+
+#upload .filelist div.file-panel {
+    position: absolute;
+    height: 0;
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0;
+    background: rgba(0, 0, 0, 0.5);
+    width: 100%;
+    top: 0;
+    left: 0;
+    overflow: hidden;
+    z-index: 300;
+}
+
+#upload .filelist div.file-panel span {
+    width: 24px;
+    height: 24px;
+    display: inline;
+    float: right;
+    text-indent: -9999px;
+    overflow: hidden;
+    background: url(./images/icons.png) no-repeat;
+    background: url(./images/icons.gif) no-repeat \9;
+    margin: 5px 1px 1px;
+    cursor: pointer;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+#upload .filelist div.file-panel span.rotateLeft {
+    display:none;
+    background-position: 0 -24px;
+}
+
+#upload .filelist div.file-panel span.rotateLeft:hover {
+    background-position: 0 0;
+}
+
+#upload .filelist div.file-panel span.rotateRight {
+    display:none;
+    background-position: -24px -24px;
+}
+
+#upload .filelist div.file-panel span.rotateRight:hover {
+    background-position: -24px 0;
+}
+
+#upload .filelist div.file-panel span.cancel {
+    background-position: -48px -24px;
+}
+
+#upload .filelist div.file-panel span.cancel:hover {
+    background-position: -48px 0;
+}
+
+#upload .statusBar {
+    height: 45px;
+    border-bottom: 1px solid #dadada;
+    margin: 0 10px;
+    padding: 0;
+    line-height: 45px;
+    vertical-align: middle;
+    position: relative;
+}
+
+#upload .statusBar .progress {
+    border: 1px solid #1483d8;
+    width: 198px;
+    background: #fff;
+    height: 18px;
+    position: absolute;
+    top: 12px;
+    display: none;
+    text-align: center;
+    line-height: 18px;
+    color: #6dbfff;
+    margin: 0 10px 0 0;
+}
+#upload .statusBar .progress span.percentage {
+    width: 0;
+    height: 100%;
+    left: 0;
+    top: 0;
+    background: #1483d8;
+    position: absolute;
+}
+#upload .statusBar .progress span.text {
+    position: relative;
+    z-index: 10;
+}
+
+#upload .statusBar .info {
+    display: inline-block;
+    font-size: 14px;
+    color: #666666;
+}
+
+#upload .statusBar .btns {
+    position: absolute;
+    top: 7px;
+    right: 0;
+    line-height: 30px;
+}
+
+#filePickerBtn {
+    display: inline-block;
+    float: left;
+}
+#upload .statusBar .btns .webuploader-pick,
+#upload .statusBar .btns .uploadBtn,
+#upload .statusBar .btns .uploadBtn.state-uploading,
+#upload .statusBar .btns .uploadBtn.state-paused {
+    background: #ffffff;
+    border: 1px solid #cfcfcf;
+    color: #565656;
+    padding: 0 18px;
+    display: inline-block;
+    border-radius: 3px;
+    margin-left: 10px;
+    cursor: pointer;
+    font-size: 14px;
+    float: left;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+#upload .statusBar .btns .webuploader-pick-hover,
+#upload .statusBar .btns .uploadBtn:hover,
+#upload .statusBar .btns .uploadBtn.state-uploading:hover,
+#upload .statusBar .btns .uploadBtn.state-paused:hover {
+    background: #f0f0f0;
+}
+
+#upload .statusBar .btns .uploadBtn,
+#upload .statusBar .btns .uploadBtn.state-paused{
+    background: #00b7ee;
+    color: #fff;
+    border-color: transparent;
+}
+#upload .statusBar .btns .uploadBtn:hover,
+#upload .statusBar .btns .uploadBtn.state-paused:hover{
+    background: #00a2d4;
+}
+
+#upload .statusBar .btns .uploadBtn.disabled {
+    pointer-events: none;
+    filter:alpha(opacity=60);
+    -moz-opacity:0.6;
+    -khtml-opacity: 0.6;
+    opacity: 0.6;
+}
+
+
+
+/* 图片管理样式 */
+#online {
+    width: 100%;
+    height: 336px;
+    padding: 10px 0 0 0;
+}
+#online #fileList{
+    width: 100%;
+    height: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+}
+#online ul {
+    display: block;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+#online li {
+    float: left;
+    display: block;
+    list-style: none;
+    padding: 0;
+    width: 113px;
+    height: 113px;
+    margin: 0 0 9px 9px;
+    *margin: 0 0 6px 6px;
+    background-color: #eee;
+    overflow: hidden;
+    cursor: pointer;
+    position: relative;
+}
+#online li.clearFloat {
+    float: none;
+    clear: both;
+    display: block;
+    width:0;
+    height:0;
+    margin: 0;
+    padding: 0;
+}
+#online li img {
+    cursor: pointer;
+}
+#online li div.file-wrapper {
+    cursor: pointer;
+    position: absolute;
+    display: block;
+    width: 111px;
+    height: 111px;
+    border: 1px solid #eee;
+    background: url("./images/bg.png") repeat;
+}
+#online li div span.file-title{
+    display: block;
+    padding: 0 3px;
+    margin: 3px 0 0 0;
+    font-size: 12px;
+    height: 13px;
+    color: #555555;
+    text-align: center;
+    width: 107px;
+    white-space: nowrap;
+    word-break: break-all;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+#online li .icon {
+    cursor: pointer;
+    width: 113px;
+    height: 113px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    border: 0;
+    background-repeat: no-repeat;
+}
+#online li .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+}
+#online li.selected .icon {
+    background-image: url(images/success.png);
+    background-image: url(images/success.gif) \9;
+    background-position: 75px 75px;
+}
+#online li.selected .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+    background-position: 72px 72px;
+}
+
+
+/* 在线文件的文件预览图标 */
+i.file-preview {
+    display: block;
+    margin: 10px auto;
+    width: 70px;
+    height: 70px;
+    background-image: url("./images/file-icons.png");
+    background-image: url("./images/file-icons.gif") \9;
+    background-position: -140px center;
+    background-repeat: no-repeat;
+}
+i.file-preview.file-type-dir{
+    background-position: 0 center;
+}
+i.file-preview.file-type-file{
+    background-position: -140px center;
+}
+i.file-preview.file-type-filelist{
+    background-position: -210px center;
+}
+i.file-preview.file-type-zip,
+i.file-preview.file-type-rar,
+i.file-preview.file-type-7z,
+i.file-preview.file-type-tar,
+i.file-preview.file-type-gz,
+i.file-preview.file-type-bz2{
+    background-position: -280px center;
+}
+i.file-preview.file-type-xls,
+i.file-preview.file-type-xlsx{
+    background-position: -350px center;
+}
+i.file-preview.file-type-doc,
+i.file-preview.file-type-docx{
+    background-position: -420px center;
+}
+i.file-preview.file-type-ppt,
+i.file-preview.file-type-pptx{
+    background-position: -490px center;
+}
+i.file-preview.file-type-vsd{
+    background-position: -560px center;
+}
+i.file-preview.file-type-pdf{
+    background-position: -630px center;
+}
+i.file-preview.file-type-txt,
+i.file-preview.file-type-md,
+i.file-preview.file-type-json,
+i.file-preview.file-type-htm,
+i.file-preview.file-type-xml,
+i.file-preview.file-type-html,
+i.file-preview.file-type-js,
+i.file-preview.file-type-css,
+i.file-preview.file-type-php,
+i.file-preview.file-type-jsp,
+i.file-preview.file-type-asp{
+    background-position: -700px center;
+}
+i.file-preview.file-type-apk{
+    background-position: -770px center;
+}
+i.file-preview.file-type-exe{
+    background-position: -840px center;
+}
+i.file-preview.file-type-ipa{
+    background-position: -910px center;
+}
+i.file-preview.file-type-mp4,
+i.file-preview.file-type-swf,
+i.file-preview.file-type-mkv,
+i.file-preview.file-type-avi,
+i.file-preview.file-type-flv,
+i.file-preview.file-type-mov,
+i.file-preview.file-type-mpg,
+i.file-preview.file-type-mpeg,
+i.file-preview.file-type-ogv,
+i.file-preview.file-type-webm,
+i.file-preview.file-type-rm,
+i.file-preview.file-type-rmvb{
+    background-position: -980px center;
+}
+i.file-preview.file-type-ogg,
+i.file-preview.file-type-wav,
+i.file-preview.file-type-wmv,
+i.file-preview.file-type-mid,
+i.file-preview.file-type-mp3{
+    background-position: -1050px center;
+}
+i.file-preview.file-type-jpg,
+i.file-preview.file-type-jpeg,
+i.file-preview.file-type-gif,
+i.file-preview.file-type-bmp,
+i.file-preview.file-type-png,
+i.file-preview.file-type-psd{
+    background-position: -140px center;
+}

+ 60 - 0
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/attachment.html

@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>ueditor图片对话框</title>
+    <script type="text/javascript" src="../internal.js"></script>
+
+    <!-- jquery -->
+    <script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js"></script>
+
+    <!-- webuploader -->
+    <script src="../../third-party/webuploader/webuploader.min.js"></script>
+    <link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">
+
+    <!-- attachment dialog -->
+    <link rel="stylesheet" href="attachment.css" type="text/css" />
+</head>
+<body>
+
+    <div class="wrapper">
+        <div id="tabhead" class="tabhead">
+            <span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span>
+            <span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>
+        </div>
+        <div id="tabbody" class="tabbody">
+            <!-- 上传图片 -->
+            <div id="upload" class="panel focus">
+                <div id="queueList" class="queueList">
+                    <div class="statusBar element-invisible">
+                        <div class="progress">
+                            <span class="text">0%</span>
+                            <span class="percentage"></span>
+                        </div><div class="info"></div>
+                        <div class="btns">
+                            <div id="filePickerBtn"></div>
+                            <div class="uploadBtn"><var id="lang_start_upload"></var></div>
+                        </div>
+                    </div>
+                    <div id="dndArea" class="placeholder">
+                        <div class="filePickerContainer">
+                            <div id="filePickerReady"></div>
+                        </div>
+                    </div>
+                    <ul class="filelist element-invisible">
+                        <li id="filePickerBlock" class="filePickerBlock"></li>
+                    </ul>
+                </div>
+            </div>
+
+            <!-- 在线图片 -->
+            <div id="online" class="panel">
+                <div id="fileList"><var id="lang_imgLoading"></var></div>
+            </div>
+
+        </div>
+    </div>
+    <script type="text/javascript" src="attachment.js"></script>
+
+</body>
+</html>

+ 754 - 0
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/attachment.js

@@ -0,0 +1,754 @@
+/**
+ * User: Jinqn
+ * Date: 14-04-08
+ * Time: 下午16:34
+ * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片
+ */
+
+(function () {
+
+    var uploadFile,
+        onlineFile;
+
+    window.onload = function () {
+        initTabs();
+        initButtons();
+    };
+
+    /* 初始化tab标签 */
+    function initTabs() {
+        var tabs = $G('tabhead').children;
+        for (var i = 0; i < tabs.length; i++) {
+            domUtils.on(tabs[i], "click", function (e) {
+                var target = e.target || e.srcElement;
+                setTabFocus(target.getAttribute('data-content-id'));
+            });
+        }
+
+        setTabFocus('upload');
+    }
+
+    /* 初始化tabbody */
+    function setTabFocus(id) {
+        if(!id) return;
+        var i, bodyId, tabs = $G('tabhead').children;
+        for (i = 0; i < tabs.length; i++) {
+            bodyId = tabs[i].getAttribute('data-content-id')
+            if (bodyId == id) {
+                domUtils.addClass(tabs[i], 'focus');
+                domUtils.addClass($G(bodyId), 'focus');
+            } else {
+                domUtils.removeClasses(tabs[i], 'focus');
+                domUtils.removeClasses($G(bodyId), 'focus');
+            }
+        }
+        switch (id) {
+            case 'upload':
+                uploadFile = uploadFile || new UploadFile('queueList');
+                break;
+            case 'online':
+                onlineFile = onlineFile || new OnlineFile('fileList');
+                break;
+        }
+    }
+
+    /* 初始化onok事件 */
+    function initButtons() {
+
+        dialog.onok = function () {
+            var list = [], id, tabs = $G('tabhead').children;
+            for (var i = 0; i < tabs.length; i++) {
+                if (domUtils.hasClass(tabs[i], 'focus')) {
+                    id = tabs[i].getAttribute('data-content-id');
+                    break;
+                }
+            }
+
+            switch (id) {
+                case 'upload':
+                    list = uploadFile.getInsertList();
+                    var count = uploadFile.getQueueCount();
+                    if (count) {
+                        $('.info', '#queueList').html('<span style="color:red;">' + '还有2个未上传文件'.replace(/[\d]/, count) + '</span>');
+                        return false;
+                    }
+                    break;
+                case 'online':
+                    list = onlineFile.getInsertList();
+                    break;
+            }
+
+            editor.execCommand('insertfile', list);
+        };
+    }
+
+
+    /* 上传附件 */
+    function UploadFile(target) {
+        this.$wrap = target.constructor == String ? $('#' + target) : $(target);
+        this.init();
+    }
+    UploadFile.prototype = {
+        init: function () {
+            this.fileList = [];
+            this.initContainer();
+            this.initUploader();
+        },
+        initContainer: function () {
+            this.$queue = this.$wrap.find('.filelist');
+        },
+        /* 初始化容器 */
+        initUploader: function () {
+            var _this = this,
+                $ = jQuery,    // just in case. Make sure it's not an other libaray.
+                $wrap = _this.$wrap,
+            // 图片容器
+                $queue = $wrap.find('.filelist'),
+            // 状态栏,包括进度和控制按钮
+                $statusBar = $wrap.find('.statusBar'),
+            // 文件总体选择信息。
+                $info = $statusBar.find('.info'),
+            // 上传按钮
+                $upload = $wrap.find('.uploadBtn'),
+            // 上传按钮
+                $filePickerBtn = $wrap.find('.filePickerBtn'),
+            // 上传按钮
+                $filePickerBlock = $wrap.find('.filePickerBlock'),
+            // 没选择文件之前的内容。
+                $placeHolder = $wrap.find('.placeholder'),
+            // 总体进度条
+                $progress = $statusBar.find('.progress').hide(),
+            // 添加的文件数量
+                fileCount = 0,
+            // 添加的文件总大小
+                fileSize = 0,
+            // 优化retina, 在retina下这个值是2
+                ratio = window.devicePixelRatio || 1,
+            // 缩略图大小
+                thumbnailWidth = 113 * ratio,
+                thumbnailHeight = 113 * ratio,
+            // 可能有pedding, ready, uploading, confirm, done.
+                state = '',
+            // 所有文件的进度信息,key为file id
+                percentages = {},
+                supportTransition = (function () {
+                    var s = document.createElement('p').style,
+                        r = 'transition' in s ||
+                            'WebkitTransition' in s ||
+                            'MozTransition' in s ||
+                            'msTransition' in s ||
+                            'OTransition' in s;
+                    s = null;
+                    return r;
+                })(),
+            // WebUploader实例
+                uploader,
+                actionUrl = editor.getActionUrl(editor.getOpt('fileActionName')),
+                fileMaxSize = editor.getOpt('fileMaxSize'),
+                acceptExtensions = (editor.getOpt('fileAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');;
+
+            if (!WebUploader.Uploader.support()) {
+                $('#filePickerReady').after($('<div>').html(lang.errorNotSupport)).hide();
+                return;
+            } else if (!editor.getOpt('fileActionName')) {
+                $('#filePickerReady').after($('<div>').html(lang.errorLoadConfig)).hide();
+                return;
+            }
+
+            uploader = _this.uploader = WebUploader.create({
+                pick: {
+                    id: '#filePickerReady',
+                    label: lang.uploadSelectFile
+                },
+                swf: '../../third-party/webuploader/Uploader.swf',
+                server: actionUrl,
+                fileVal: editor.getOpt('fileFieldName'),
+                duplicate: true,
+                fileSingleSizeLimit: fileMaxSize,
+                compress: false
+            });
+            uploader.addButton({
+                id: '#filePickerBlock'
+            });
+            uploader.addButton({
+                id: '#filePickerBtn',
+                label: lang.uploadAddFile
+            });
+
+            setState('pedding');
+
+            // 当有文件添加进来时执行,负责view的创建
+            function addFile(file) {
+                var $li = $('<li id="' + file.id + '">' +
+                        '<p class="title">' + file.name + '</p>' +
+                        '<p class="imgWrap"></p>' +
+                        '<p class="progress"><span></span></p>' +
+                        '</li>'),
+
+                    $btns = $('<div class="file-panel">' +
+                        '<span class="cancel">' + lang.uploadDelete + '</span>' +
+                        '<span class="rotateRight">' + lang.uploadTurnRight + '</span>' +
+                        '<span class="rotateLeft">' + lang.uploadTurnLeft + '</span></div>').appendTo($li),
+                    $prgress = $li.find('p.progress span'),
+                    $wrap = $li.find('p.imgWrap'),
+                    $info = $('<p class="error"></p>').hide().appendTo($li),
+
+                    showError = function (code) {
+                        switch (code) {
+                            case 'exceed_size':
+                                text = lang.errorExceedSize;
+                                break;
+                            case 'interrupt':
+                                text = lang.errorInterrupt;
+                                break;
+                            case 'http':
+                                text = lang.errorHttp;
+                                break;
+                            case 'not_allow_type':
+                                text = lang.errorFileType;
+                                break;
+                            default:
+                                text = lang.errorUploadRetry;
+                                break;
+                        }
+                        $info.text(text).show();
+                    };
+
+                if (file.getStatus() === 'invalid') {
+                    showError(file.statusText);
+                } else {
+                    $wrap.text(lang.uploadPreview);
+                    if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) {
+                        $wrap.empty().addClass('notimage').append('<i class="file-preview file-type-' + file.ext.toLowerCase() + '"></i>' +
+                        '<span class="file-title" title="' + file.name + '">' + file.name + '</span>');
+                    } else {
+                        if (browser.ie && browser.version <= 7) {
+                            $wrap.text(lang.uploadNoPreview);
+                        } else {
+                            uploader.makeThumb(file, function (error, src) {
+                                if (error || !src) {
+                                    $wrap.text(lang.uploadNoPreview);
+                                } else {
+                                    var $img = $('<img src="' + src + '">');
+                                    $wrap.empty().append($img);
+                                    $img.on('error', function () {
+                                        $wrap.text(lang.uploadNoPreview);
+                                    });
+                                }
+                            }, thumbnailWidth, thumbnailHeight);
+                        }
+                    }
+                    percentages[ file.id ] = [ file.size, 0 ];
+                    file.rotation = 0;
+
+                    /* 检查文件格式 */
+                    if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) {
+                        showError('not_allow_type');
+                        uploader.removeFile(file);
+                    }
+                }
+
+                file.on('statuschange', function (cur, prev) {
+                    if (prev === 'progress') {
+                        $prgress.hide().width(0);
+                    } else if (prev === 'queued') {
+                        $li.off('mouseenter mouseleave');
+                        $btns.remove();
+                    }
+                    // 成功
+                    if (cur === 'error' || cur === 'invalid') {
+                        showError(file.statusText);
+                        percentages[ file.id ][ 1 ] = 1;
+                    } else if (cur === 'interrupt') {
+                        showError('interrupt');
+                    } else if (cur === 'queued') {
+                        percentages[ file.id ][ 1 ] = 0;
+                    } else if (cur === 'progress') {
+                        $info.hide();
+                        $prgress.css('display', 'block');
+                    } else if (cur === 'complete') {
+                    }
+
+                    $li.removeClass('state-' + prev).addClass('state-' + cur);
+                });
+
+                $li.on('mouseenter', function () {
+                    $btns.stop().animate({height: 30});
+                });
+                $li.on('mouseleave', function () {
+                    $btns.stop().animate({height: 0});
+                });
+
+                $btns.on('click', 'span', function () {
+                    var index = $(this).index(),
+                        deg;
+
+                    switch (index) {
+                        case 0:
+                            uploader.removeFile(file);
+                            return;
+                        case 1:
+                            file.rotation += 90;
+                            break;
+                        case 2:
+                            file.rotation -= 90;
+                            break;
+                    }
+
+                    if (supportTransition) {
+                        deg = 'rotate(' + file.rotation + 'deg)';
+                        $wrap.css({
+                            '-webkit-transform': deg,
+                            '-mos-transform': deg,
+                            '-o-transform': deg,
+                            'transform': deg
+                        });
+                    } else {
+                        $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')');
+                    }
+
+                });
+
+                $li.insertBefore($filePickerBlock);
+            }
+
+            // 负责view的销毁
+            function removeFile(file) {
+                var $li = $('#' + file.id);
+                delete percentages[ file.id ];
+                updateTotalProgress();
+                $li.off().find('.file-panel').off().end().remove();
+            }
+
+            function updateTotalProgress() {
+                var loaded = 0,
+                    total = 0,
+                    spans = $progress.children(),
+                    percent;
+
+                $.each(percentages, function (k, v) {
+                    total += v[ 0 ];
+                    loaded += v[ 0 ] * v[ 1 ];
+                });
+
+                percent = total ? loaded / total : 0;
+
+                spans.eq(0).text(Math.round(percent * 100) + '%');
+                spans.eq(1).css('width', Math.round(percent * 100) + '%');
+                updateStatus();
+            }
+
+            function setState(val, files) {
+
+                if (val != state) {
+
+                    var stats = uploader.getStats();
+
+                    $upload.removeClass('state-' + state);
+                    $upload.addClass('state-' + val);
+
+                    switch (val) {
+
+                        /* 未选择文件 */
+                        case 'pedding':
+                            $queue.addClass('element-invisible');
+                            $statusBar.addClass('element-invisible');
+                            $placeHolder.removeClass('element-invisible');
+                            $progress.hide(); $info.hide();
+                            uploader.refresh();
+                            break;
+
+                        /* 可以开始上传 */
+                        case 'ready':
+                            $placeHolder.addClass('element-invisible');
+                            $queue.removeClass('element-invisible');
+                            $statusBar.removeClass('element-invisible');
+                            $progress.hide(); $info.show();
+                            $upload.text(lang.uploadStart);
+                            uploader.refresh();
+                            break;
+
+                        /* 上传中 */
+                        case 'uploading':
+                            $progress.show(); $info.hide();
+                            $upload.text(lang.uploadPause);
+                            break;
+
+                        /* 暂停上传 */
+                        case 'paused':
+                            $progress.show(); $info.hide();
+                            $upload.text(lang.uploadContinue);
+                            break;
+
+                        case 'confirm':
+                            $progress.show(); $info.hide();
+                            $upload.text(lang.uploadStart);
+
+                            stats = uploader.getStats();
+                            if (stats.successNum && !stats.uploadFailNum) {
+                                setState('finish');
+                                return;
+                            }
+                            break;
+
+                        case 'finish':
+                            $progress.hide(); $info.show();
+                            if (stats.uploadFailNum) {
+                                $upload.text(lang.uploadRetry);
+                            } else {
+                                $upload.text(lang.uploadStart);
+                            }
+                            break;
+                    }
+
+                    state = val;
+                    updateStatus();
+
+                }
+
+                if (!_this.getQueueCount()) {
+                    $upload.addClass('disabled')
+                } else {
+                    $upload.removeClass('disabled')
+                }
+
+            }
+
+            function updateStatus() {
+                var text = '', stats;
+
+                if (state === 'ready') {
+                    text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize));
+                } else if (state === 'confirm') {
+                    stats = uploader.getStats();
+                    if (stats.uploadFailNum) {
+                        text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum);
+                    }
+                } else {
+                    stats = uploader.getStats();
+                    text = lang.updateStatusFinish.replace('_', fileCount).
+                        replace('_KB', WebUploader.formatSize(fileSize)).
+                        replace('_', stats.successNum);
+
+                    if (stats.uploadFailNum) {
+                        text += lang.updateStatusError.replace('_', stats.uploadFailNum);
+                    }
+                }
+
+                $info.html(text);
+            }
+
+            uploader.on('fileQueued', function (file) {
+                fileCount++;
+                fileSize += file.size;
+
+                if (fileCount === 1) {
+                    $placeHolder.addClass('element-invisible');
+                    $statusBar.show();
+                }
+
+                addFile(file);
+            });
+
+            uploader.on('fileDequeued', function (file) {
+                fileCount--;
+                fileSize -= file.size;
+
+                removeFile(file);
+                updateTotalProgress();
+            });
+
+            uploader.on('filesQueued', function (file) {
+                if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) {
+                    setState('ready');
+                }
+                updateTotalProgress();
+            });
+
+            uploader.on('all', function (type, files) {
+                switch (type) {
+                    case 'uploadFinished':
+                        setState('confirm', files);
+                        break;
+                    case 'startUpload':
+                        /* 添加额外的GET参数 */
+                        var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '',
+                            url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params);
+                        uploader.option('server', url);
+                        setState('uploading', files);
+                        break;
+                    case 'stopUpload':
+                        setState('paused', files);
+                        break;
+                }
+            });
+
+            uploader.on('uploadBeforeSend', function (file, data, header) {
+                //这里可以通过data对象添加POST参数
+                header['X_Requested_With'] = 'XMLHttpRequest';
+            });
+
+            uploader.on('uploadProgress', function (file, percentage) {
+                var $li = $('#' + file.id),
+                    $percent = $li.find('.progress span');
+
+                $percent.css('width', percentage * 100 + '%');
+                percentages[ file.id ][ 1 ] = percentage;
+                updateTotalProgress();
+            });
+
+            uploader.on('uploadSuccess', function (file, ret) {
+                var $file = $('#' + file.id);
+                try {
+                    var responseText = (ret._raw || ret),
+                        json = utils.str2json(responseText);
+                    if (json.state == 'SUCCESS') {
+                        _this.fileList.push(json);
+                        $file.append('<span class="success"></span>');
+                    } else {
+                        $file.find('.error').text(json.state).show();
+                    }
+                } catch (e) {
+                    $file.find('.error').text(lang.errorServerUpload).show();
+                }
+            });
+
+            uploader.on('uploadError', function (file, code) {
+            });
+            uploader.on('error', function (code, file) {
+                if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') {
+                    addFile(file);
+                }
+            });
+            uploader.on('uploadComplete', function (file, ret) {
+            });
+
+            $upload.on('click', function () {
+                if ($(this).hasClass('disabled')) {
+                    return false;
+                }
+
+                if (state === 'ready') {
+                    uploader.upload();
+                } else if (state === 'paused') {
+                    uploader.upload();
+                } else if (state === 'uploading') {
+                    uploader.stop();
+                }
+            });
+
+            $upload.addClass('state-' + state);
+            updateTotalProgress();
+        },
+        getQueueCount: function () {
+            var file, i, status, readyFile = 0, files = this.uploader.getFiles();
+            for (i = 0; file = files[i++]; ) {
+                status = file.getStatus();
+                if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++;
+            }
+            return readyFile;
+        },
+        getInsertList: function () {
+            var i, link, data, list = [],
+                prefix = editor.getOpt('fileUrlPrefix');
+            for (i = 0; i < this.fileList.length; i++) {
+                data = this.fileList[i];
+                link = data.url;
+                list.push({
+                    title: data.original || link.substr(link.lastIndexOf('/') + 1),
+                    url: prefix + link
+                });
+            }
+            return list;
+        }
+    };
+
+
+    /* 在线附件 */
+    function OnlineFile(target) {
+        this.container = utils.isString(target) ? document.getElementById(target) : target;
+        this.init();
+    }
+    OnlineFile.prototype = {
+        init: function () {
+            this.initContainer();
+            this.initEvents();
+            this.initData();
+        },
+        /* 初始化容器 */
+        initContainer: function () {
+            this.container.innerHTML = '';
+            this.list = document.createElement('ul');
+            this.clearFloat = document.createElement('li');
+
+            domUtils.addClass(this.list, 'list');
+            domUtils.addClass(this.clearFloat, 'clearFloat');
+
+            this.list.appendChild(this.clearFloat);
+            this.container.appendChild(this.list);
+        },
+        /* 初始化滚动事件,滚动到地步自动拉取数据 */
+        initEvents: function () {
+            var _this = this;
+
+            /* 滚动拉取图片 */
+            domUtils.on($G('fileList'), 'scroll', function(e){
+                var panel = this;
+                if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) {
+                    _this.getFileData();
+                }
+            });
+            /* 选中图片 */
+            domUtils.on(this.list, 'click', function (e) {
+                var target = e.target || e.srcElement,
+                    li = target.parentNode;
+
+                if (li.tagName.toLowerCase() == 'li') {
+                    if (domUtils.hasClass(li, 'selected')) {
+                        domUtils.removeClasses(li, 'selected');
+                    } else {
+                        domUtils.addClass(li, 'selected');
+                    }
+                }
+            });
+        },
+        /* 初始化第一次的数据 */
+        initData: function () {
+
+            /* 拉取数据需要使用的值 */
+            this.state = 0;
+            this.listSize = editor.getOpt('fileManagerListSize');
+            this.listIndex = 0;
+            this.listEnd = false;
+
+            /* 第一次拉取数据 */
+            this.getFileData();
+        },
+        /* 向后台拉取图片列表数据 */
+        getFileData: function () {
+            var _this = this;
+
+            if(!_this.listEnd && !this.isLoadingData) {
+                this.isLoadingData = true;
+                ajax.request(editor.getActionUrl(editor.getOpt('fileManagerActionName')), {
+                    timeout: 100000,
+                    data: utils.extend({
+                            start: this.listIndex,
+                            size: this.listSize
+                        }, editor.queryCommandValue('serverparam')),
+                    method: 'get',
+                    onsuccess: function (r) {
+                        try {
+                            var json = eval('(' + r.responseText + ')');
+                            if (json.state == 'SUCCESS') {
+                                _this.pushData(json.list);
+                                _this.listIndex = parseInt(json.start) + parseInt(json.list.length);
+                                if(_this.listIndex >= json.total) {
+                                    _this.listEnd = true;
+                                }
+                                _this.isLoadingData = false;
+                            }
+                        } catch (e) {
+                            if(r.responseText.indexOf('ue_separate_ue') != -1) {
+                                var list = r.responseText.split(r.responseText);
+                                _this.pushData(list);
+                                _this.listIndex = parseInt(list.length);
+                                _this.listEnd = true;
+                                _this.isLoadingData = false;
+                            }
+                        }
+                    },
+                    onerror: function () {
+                        _this.isLoadingData = false;
+                    }
+                });
+            }
+        },
+        /* 添加图片到列表界面上 */
+        pushData: function (list) {
+            var i, item, img, filetype, preview, icon, _this = this,
+                urlPrefix = editor.getOpt('fileManagerUrlPrefix');
+            for (i = 0; i < list.length; i++) {
+                if(list[i] && list[i].url) {
+                    item = document.createElement('li');
+                    icon = document.createElement('span');
+                    filetype = list[i].url.substr(list[i].url.lastIndexOf('.') + 1);
+
+                    if ( "png|jpg|jpeg|gif|bmp".indexOf(filetype) != -1 ) {
+                        preview = document.createElement('img');
+                        domUtils.on(preview, 'load', (function(image){
+                            return function(){
+                                _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight);
+                            };
+                        })(preview));
+                        preview.width = 113;
+                        preview.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) );
+                    } else {
+                        var ic = document.createElement('i'),
+                            textSpan = document.createElement('span');
+                        textSpan.innerHTML = list[i].url.substr(list[i].url.lastIndexOf('/') + 1);
+                        preview = document.createElement('div');
+                        preview.appendChild(ic);
+                        preview.appendChild(textSpan);
+                        domUtils.addClass(preview, 'file-wrapper');
+                        domUtils.addClass(textSpan, 'file-title');
+                        domUtils.addClass(ic, 'file-type-' + filetype);
+                        domUtils.addClass(ic, 'file-preview');
+                    }
+                    domUtils.addClass(icon, 'icon');
+                    item.setAttribute('data-url', urlPrefix + list[i].url);
+                    if (list[i].original) {
+                        item.setAttribute('data-title', list[i].original);
+                    }
+
+                    item.appendChild(preview);
+                    item.appendChild(icon);
+                    this.list.insertBefore(item, this.clearFloat);
+                }
+            }
+        },
+        /* 改变图片大小 */
+        scale: function (img, w, h, type) {
+            var ow = img.width,
+                oh = img.height;
+
+            if (type == 'justify') {
+                if (ow >= oh) {
+                    img.width = w;
+                    img.height = h * oh / ow;
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
+                } else {
+                    img.width = w * ow / oh;
+                    img.height = h;
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
+                }
+            } else {
+                if (ow >= oh) {
+                    img.width = w * ow / oh;
+                    img.height = h;
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
+                } else {
+                    img.width = w;
+                    img.height = h * oh / ow;
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
+                }
+            }
+        },
+        getInsertList: function () {
+            var i, lis = this.list.children, list = [];
+            for (i = 0; i < lis.length; i++) {
+                if (domUtils.hasClass(lis[i], 'selected')) {
+                    var url = lis[i].getAttribute('data-url');
+                    var title = lis[i].getAttribute('data-title') || url.substr(url.lastIndexOf('/') + 1);
+                    list.push({
+                        title: title,
+                        url: url
+                    });
+                }
+            }
+            return list;
+        }
+    };
+
+
+})();

二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_chm.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_default.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_doc.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_exe.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_jpg.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_mp3.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_mv.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_pdf.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_ppt.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_psd.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_rar.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_txt.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/fileTypeImages/icon_xls.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/alignicon.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/alignicon.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/bg.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/file-icons.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/file-icons.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/icons.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/icons.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/image.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/progress.png


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/success.gif


二进制
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/attachment/images/success.png


+ 94 - 0
src/Masuit.MyBlogs.WebApp/Assets/UEditor/dialogs/background/background.css

@@ -0,0 +1,94 @@
+.wrapper{ width: 424px;margin: 10px auto; zoom:1;position: relative}
+.tabbody{height:225px;}
+.tabbody .panel { position: absolute;width:100%; height:100%;background: #fff; display: none;}
+.tabbody .focus { display: block;}
+
+body{font-size: 12px;color: #888;overflow: hidden;}
+input,label{vertical-align:middle}
+.clear{clear: both;}
+.pl{padding-left: 18px;padding-left: 23px\9;}
+
+#imageList {width: 420px;height: 215px;margin-top: 10px;overflow: hidden;overflow-y: auto;}
+#imageList div {float: left;width: 100px;height: 95px;margin: 5px 10px;}
+#imageList img {cursor: pointer;border: 2px solid white;}
+
+.bgarea{margin: 10px;padding: 5px;height: 84%;border: 1px solid #A8A297;}
+.content div{margin: 10px 0 10px 5px;}
+.content .iptradio{margin: 0px 5px 5px 0px;}
+.txt{width:280px;}
+
+.wrapcolor{height: 19px;}
+div.color{float: left;margin: 0;}
+#colorPicker{width: 17px;height: 17px;border: 1px solid #CCC;display: inline-block;border-radius: 3px;box-shadow: 2px 2px 5px #D3D6DA;margin: 0;float: left;}
+div.alignment,#custom{margin-left: 23px;margin-left: 28px\9;}
+#custom input{height: 15px;min-height: 15px;width:20px;}
+#repeatType{width:100px;}
+
+
+/* 图片管理样式 */
+#imgManager {
+    width: 100%;
+    height: 225px;
+}
+#imgManager #imageList{
+    width: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+}
+#imgManager ul {
+    display: block;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+#imgManager li {
+    float: left;
+    display: block;
+    list-style: none;
+    padding: 0;
+    width: 113px;
+    height: 113px;
+    margin: 9px 0 0 19px;
+    background-color: #eee;
+    overflow: hidden;
+    cursor: pointer;
+    position: relative;
+}
+#imgManager li.clearFloat {
+    float: none;
+    clear: both;
+    display: block;
+    width:0;
+    height:0;
+    margin: 0;
+    padding: 0;
+}
+#imgManager li img {
+    cursor: pointer;
+}
+#imgManager li .icon {
+    cursor: pointer;
+    width: 113px;
+    height: 113px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    border: 0;
+    background-repeat: no-repeat;
+}
+#imgManager li .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+}
+#imgManager li.selected .icon {
+    background-image: url(images/success.png);
+    background-position: 75px 75px;
+}
+#imgManager li.selected .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+    background-position: 72px 72px;
+}

部分文件因为文件数量过多而无法显示