Net筆記-EF/EF Core/Dapper等ORM開發記錄


 個人備查筆記

 

 

Q.EF Core 視圖的模型映射:

  Note:EF的CreateDbDatabase和數據遷移並不會自動創建視圖,需要手動創建...

  簡單例子:

  配置類:

    public class View_AccountFemaleEFConfig : IEntityTypeConfiguration<View_AccountFemale>
    {
        public void Configure(EntityTypeBuilder<View_AccountFemale> builder)
        {
            #region //水平拆分處理處
            builder.ToView<View_AccountFemale>("View_AccountFemale").SetupBaseEntity();
            #endregion
        }
    }

    上下文:

 public class ExamContext : DbContext
    {
        virtual public DbSet<View_AccountFemale> view_AccountFemales { get; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // Database 必須存在 View_AccountFemale 視圖,否則將報錯
            modelBuilder.ApplyConfiguration<View_AccountFemale>(new View_AccountFemaleEFConfig());

            base.OnModelCreating(modelBuilder);
        }

 

Q:EF DateTime 默認值多數據兼容問題:

mysql:NOW()或sysdate()

Sql Server: GetDate()

EF兼容使用 ANSI SQL:

builder.Property(x => x.UpdatedOn).HasDefaultValueSql("CURRENT_TIMESTAMP");

 

 

Q:EF/Linq語句轉Raw SQL:

代碼轉載備查,

 

轉載來源:https://stackoverflow.com/questions/37527783/get-sql-code-from-an-entity-framework-core-iqueryablet

 

EF Core 2.x:

    public static class QueryableExtensions
    {
        private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler"); private static readonly FieldInfo QueryModelGeneratorField = typeof(QueryCompiler).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryModelGenerator"); private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database"); private static readonly PropertyInfo DatabaseDependenciesField = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); public static string ToSql<TEntity>(this IQueryable<TEntity> query) { var queryCompiler = (QueryCompiler) QueryCompilerField.GetValue(query.Provider); var queryModelGenerator = (QueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler); var queryModel = queryModelGenerator.ParseQuery(query.Expression); var database = DataBaseField.GetValue(queryCompiler); var databaseDependencies = (DatabaseDependencies) DatabaseDependenciesField.GetValue(database); var queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false); var modelVisitor = (RelationalQueryModelVisitor) queryCompilationContext.CreateQueryModelVisitor(); modelVisitor.CreateQueryExecutor<TEntity>(queryModel); var sql = modelVisitor.Queries.First().ToString(); return sql; } }

 

EF Core 3.x:

        public static string ToSql<T>(this IQueryable<T> query)
        {
            var enumerator = query.Provider.Execute<IEnumerable<T>>(query.Expression).GetEnumerator(); var enumeratorType = enumerator.GetType(); var selectFieldInfo = enumeratorType.GetField("_selectExpression", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException($"cannot find field _selectExpression on type {enumeratorType.Name}"); var sqlGeneratorFieldInfo = enumeratorType.GetField("_querySqlGeneratorFactory", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException($"cannot find field _querySqlGeneratorFactory on type {enumeratorType.Name}"); var selectExpression = selectFieldInfo.GetValue(enumerator) as SelectExpression ?? throw new InvalidOperationException($"could not get SelectExpression"); var factory = sqlGeneratorFieldInfo.GetValue(enumerator) as IQuerySqlGeneratorFactory ?? throw new InvalidOperationException($"could not get IQuerySqlGeneratorFactory"); var sqlGenerator = factory.Create(); var command = sqlGenerator.GetCommand(selectExpression); var sql = command.CommandText; return sql; }

 

 

Q:EF的Mysql樂觀鎖實現:

  RowVersion只支持Sql Server,如果需要通用(多數據庫支持)的樂觀鎖的話:

  以EF Core 為例:

  Entity:

    abstract public class BaseEntity
    {
        public Int64 Qing_Version { get; set; } }

Config:

    public class AccountEFConfig : IEntityTypeConfiguration<Account>
    {
        public void Configure(EntityTypeBuilder<Account> builder) { EntityTypeBuilder<Account> tableBuilder = builder.ToTable("Account"); tableBuilder.Property(x => x.Qing_Version).IsConcurrencyToken(true); } }

重載重寫SaveChange/SaveChangeAsyc:

    public class BaseDBContext<DBCtx> : DbContext where DBCtx : DbContext
    {
        public override int SaveChanges() { var validationErrors = this.ChangeTracker; if (this.ChangeTracker != null) { var entities = this.ChangeTracker .Entries() .Where( x => x.State == EntityState.Modified && x.Entity != null && typeof(BaseEntity).IsAssignableFrom(x.Entity.GetType()) ) .Select(x => x) .ToList(); foreach (var entity in entities) { BaseEntity entityBase = entity.Entity as BaseEntity; entityBase.Qing_UpdateTime = DateTime.Now; entityBase.Qing_Version++; } } return base.SaveChanges(); } }

 

 

擴展閱讀:

  但當如果需要做通用的樂觀鎖支持的話,EF6.x或以上時,需要支持MySQL 的話你需要:

  https://stackoverflow.com/questions/7608619/optimistic-concurrency-with-entity-framework-and-mysql

  或

  https://www.cnblogs.com/easygame/p/4456965.html

  

  EF Core 1.x或以上,需要:

  參考 :https://long2know.com/2016/07/porting-ef6-to-ef7-or-ef-core/ 

  實現:  https://stackoverflow.com/questions/40394577/better-way-to-implement-a-row-version-with-ef-core-and-mysql

   擴展閱讀: https://www.learnentityframeworkcore.com/concurrency


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM