扩展entity framework core实现默认字符串长度,decimal精度,entity自动注册和配置

文章以efcore 2.0.0-preview2.测试验证通过。其他版本不保证使用,但是思路不会差太远。源代码,报道越短,事情越严重!文章越短,内容越精悍!

目标:
1.实现entity的自动发现和mapper设置.
2.默认字符串长度,而不是nvarchar(max).
3.decimal设置精度

实现目标1:继承RelationalModelCustomizer,重写Customize方法。

当然,我们也可以重写dbcontext的OnModelCreating方法,but,我们怎么能这么low呢。必须要用点高级玩意是吧,当然这也是更底层的扩展方式。项目里面有多个dbcontext的话,在这里集中扩展管理比较方便。
在然后,这个RelationalModelCustomizer继承自ModelCustomizer。在联想到efcore未来的版本会支持redis,nosql什么的。到时候估计还回有一个osqlModelCustomizer之类的吧,期待中......

实现目标2、3:继承自CoreConventionSetBuilder类,重写CreateConventionSet方法。

重写CreateConventionSet方法,能拿到关键的ConventionSet对象。这个对象囊括了诸多的约定配置等等。比如maxlengthattribute属性标记,stringlength属性标记,timestamp属性标记,表id的自动发现规则等等等。。。
那,我们增加2个小小的约定:字符串默认长度(StringDefaultLengthConvention),和decimal精度设置attribute(DecimalPrecisionAttributeConvention)及fluntapi方式.

文章的最后附efcore 所有的可替换扩展service。

//servie,DI注入替换.services.AddSingleton<IModelCustomizer, MyRelationalModelCustomizer>();
services.AddSingleton<ICoreConventionSetBuilder, MyCoreConventionSetBuilder>();
//实现entity的自动发现和mapper设置

public class MyRelationalModelCustomizer : RelationalModelCustomizer{  
 public MyRelationalModelCustomizer(ModelCustomizerDependencies dependencies)        : base(dependencies){}  
   public override void Customize(ModelBuilder modelBuilder, DbContext dbContext)    {      
     base.Customize(modelBuilder, dbContext);      
       var sp = (IInfrastructure<IServiceProvider>)dbContext;    
          var dbOptions = sp.Instance.GetServices<DbContextOptions>();        foreach (var item in dbOptions){      
               if (item.ContextType == dbContext.GetType())ConfigureDbContextEntityService.Configure(modelBuilder, item, dbContext);}} }

public class MyCoreConventionSetBuilder : CoreConventionSetBuilder{
   public MyCoreConventionSetBuilder(CoreConventionSetBuilderDependencies dependencies) : base(dependencies){}  
    public override ConventionSet CreateConventionSet()    {    
       var conventionSet = base.CreateConventionSet();    
          //默认字符串长度,而不是nvarchar(max).//为什么要insert(0,obj),则是因为这个默认规则要最优先处理,如果后续有规则的话就直接覆盖了。//propertyBuilder.HasMaxLength(32, ConfigurationSource.Convention);//理论上我指定了规则的级别为.Convention,应该和顺序就没有关系了。but,还没有完成测试,所以我也不知道conventionSet.PropertyAddedConventions.Insert(0, new StringDefaultLengthConvention());        //decimal设置精度conventionSet.PropertyAddedConventions.Add(new DecimalPrecisionAttributeConvention());      
            return conventionSet;} }

下面是StringDefaultLengthConvention和DecimalPrecisionAttributeConvention的实现代码

//字符串默认长度
public class StringDefaultLengthConvention : IPropertyAddedConvention {    
    public InternalPropertyBuilder Apply(InternalPropertyBuilder propertyBuilder)    {      
 if (propertyBuilder.Metadata.ClrType == typeof(string))propertyBuilder.HasMaxLength(32, ConfigurationSource.Convention);    
     return propertyBuilder;} }
//attribute方式设置decimal精度

public class DecimalPrecisionAttributeConvention : PropertyAttributeConvention<DecimalPrecisionAttribute> {  
 public override InternalPropertyBuilder Apply(InternalPropertyBuilder propertyBuilder, DecimalPrecisionAttribute attribute, MemberInfo clrMember)    {      
  if (propertyBuilder.Metadata.ClrType == typeof(decimal))propertyBuilder.HasPrecision(attribute.Precision, attribute.Scale);      
    return propertyBuilder;}
    /// <summary>
/// decimal类型设置精度
/// </summary>
/// <param name="propertyBuilder"></param>/// <param name="precision">精度</param>/// <param name="scale">小数位数</param>public static PropertyBuilder<TProperty> HasPrecision<TProperty>(this PropertyBuilder<TProperty> propertyBuilder, int precision = 18, int scale = 4) {    //fluntapi方式设置精度  ((IInfrastructure<InternalPropertyBuilder>)propertyBuilder).Instance.HasPrecision(precision, scale);  
      return propertyBuilder; }
      public static InternalPropertyBuilder HasPrecision(this InternalPropertyBuilder propertyBuilder, int precision, int scale){propertyBuilder.Relational(ConfigurationSource.Explicit).HasColumnType($"decimal({precision},{scale})");  
       return propertyBuilder; }

以上就是实现的代码,就这么几行。嗯,还是挺简单的.

--------------

以下,则是efcore的源代码。展示了如此之多的可扩展。随着DI的运用和微软的开放,嗯。用烂啦,用炸拉(^_^)

//各种规则和约定
public virtual ConventionSet AddConventions(ConventionSet conventionSet){ValueGeneratorConvention valueGeneratorConvention = new RelationalValueGeneratorConvention();ReplaceConvention(conventionSet.BaseEntityTypeChangedConventions, valueGeneratorConvention);ReplaceConvention(conventionSet.PrimaryKeyChangedConventions, valueGeneratorConvention);ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGeneratorConvention);ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGeneratorConvention);  
 var relationalColumnAttributeConvention = new RelationalColumnAttributeConvention();conventionSet.PropertyAddedConventions.Add(relationalColumnAttributeConvention);  
  var sharedTableConvention = new SharedTableConvention();conventionSet.EntityTypeAddedConventions.Add(new RelationalTableAttributeConvention());conventionSet.EntityTypeAddedConventions.Add(sharedTableConvention);conventionSet.BaseEntityTypeChangedConventions.Add(new DiscriminatorConvention());conventionSet.BaseEntityTypeChangedConventions.Add(    
     new TableNameFromDbSetConvention(Dependencies.Context?.Context, Dependencies.SetFinder));conventionSet.EntityTypeAnnotationChangedConventions.Add(sharedTableConvention);conventionSet.PropertyFieldChangedConventions.Add(relationalColumnAttributeConvention);conventionSet.PropertyAnnotationChangedConventions.Add((RelationalValueGeneratorConvention)valueGeneratorConvention);conventionSet.ForeignKeyUniquenessChangedConventions.Add(sharedTableConvention);conventionSet.ForeignKeyOwnershipChangedConventions.Add(sharedTableConvention);conventionSet.ModelBuiltConventions.Add(new RelationalTypeMappingConvention(Dependencies.TypeMapper));conventionSet.ModelBuiltConventions.Add(sharedTableConvention);conventionSet.ModelAnnotationChangedConventions.Add(new RelationalDbFunctionConvention());  
      return conventionSet; }
//还是各种规则和约定public virtual ConventionSet CreateConventionSet(){  
 var conventionSet = new ConventionSet();  
   var propertyDiscoveryConvention = new PropertyDiscoveryConvention(Dependencies.TypeMapper);  
     var keyDiscoveryConvention = new KeyDiscoveryConvention();  
      var inversePropertyAttributeConvention = new InversePropertyAttributeConvention(Dependencies.TypeMapper);
         var relationshipDiscoveryConvention = new RelationshipDiscoveryConvention(Dependencies.TypeMapper);conventionSet.EntityTypeAddedConventions.Add(new NotMappedEntityTypeAttributeConvention());conventionSet.EntityTypeAddedConventions.Add(new NotMappedMemberAttributeConvention());conventionSet.EntityTypeAddedConventions.Add(new BaseTypeDiscoveryConvention());conventionSet.EntityTypeAddedConventions.Add(propertyDiscoveryConvention);conventionSet.EntityTypeAddedConventions.Add(keyDiscoveryConvention);conventionSet.EntityTypeAddedConventions.Add(inversePropertyAttributeConvention);conventionSet.EntityTypeAddedConventions.Add(relationshipDiscoveryConvention);conventionSet.EntityTypeAddedConventions.Add(new DerivedTypeDiscoveryConvention());conventionSet.EntityTypeIgnoredConventions.Add(inversePropertyAttributeConvention);  
          var foreignKeyIndexConvention = new ForeignKeyIndexConvention();    var valueGeneratorConvention = new ValueGeneratorConvention();conventionSet.BaseEntityTypeChangedConventions.Add(propertyDiscoveryConvention);conventionSet.BaseEntityTypeChangedConventions.Add(keyDiscoveryConvention);conventionSet.BaseEntityTypeChangedConventions.Add(inversePropertyAttributeConvention);conventionSet.BaseEntityTypeChangedConventions.Add(relationshipDiscoveryConvention);conventionSet.BaseEntityTypeChangedConventions.Add(foreignKeyIndexConvention);conventionSet.BaseEntityTypeChangedConventions.Add(valueGeneratorConvention );    // An ambiguity might have been resolvedconventionSet.EntityTypeMemberIgnoredConventions.Add(inversePropertyAttributeConvention);conventionSet.EntityTypeMemberIgnoredConventions.Add(relationshipDiscoveryConvention);  
           var keyAttributeConvention = new KeyAttributeConvention();  
            var foreignKeyPropertyDiscoveryConvention = new ForeignKeyPropertyDiscoveryConvention();  
              var backingFieldConvention = new BackingFieldConvention();    var concurrencyCheckAttributeConvention = new ConcurrencyCheckAttributeConvention();    
              var databaseGeneratedAttributeConvention = new DatabaseGeneratedAttributeConvention();    
              var requiredPropertyAttributeConvention = new RequiredPropertyAttributeConvention();  
                var maxLengthAttributeConvention = new MaxLengthAttributeConvention();    
                var stringLengthAttributeConvention = new StringLengthAttributeConvention();  
                 var timestampAttributeConvention = new TimestampAttributeConvention();conventionSet.PropertyAddedConventions.Add(backingFieldConvention);conventionSet.PropertyAddedConventions.Add(concurrencyCheckAttributeConvention);conventionSet.PropertyAddedConventions.Add(databaseGeneratedAttributeConvention);conventionSet.PropertyAddedConventions.Add(requiredPropertyAttributeConvention);conventionSet.PropertyAddedConventions.Add(maxLengthAttributeConvention);conventionSet.PropertyAddedConventions.Add(stringLengthAttributeConvention);conventionSet.PropertyAddedConventions.Add(timestampAttributeConvention);conventionSet.PropertyAddedConventions.Add(keyDiscoveryConvention);conventionSet.PropertyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.PropertyAddedConventions.Add(keyAttributeConvention);conventionSet.PrimaryKeyChangedConventions.Add(valueGeneratorConvention);conventionSet.KeyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.KeyAddedConventions.Add(foreignKeyIndexConvention);conventionSet.KeyRemovedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.KeyRemovedConventions.Add(foreignKeyIndexConvention);conventionSet.KeyRemovedConventions.Add(keyDiscoveryConvention);  
                   var cascadeDeleteConvention = new CascadeDeleteConvention();conventionSet.ForeignKeyAddedConventions.Add(new ForeignKeyAttributeConvention(Dependencies.TypeMapper));conventionSet.ForeignKeyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.ForeignKeyAddedConventions.Add(keyDiscoveryConvention);conventionSet.ForeignKeyAddedConventions.Add(valueGeneratorConvention );conventionSet.ForeignKeyAddedConventions.Add(cascadeDeleteConvention);conventionSet.ForeignKeyAddedConventions.Add(foreignKeyIndexConvention);conventionSet.ForeignKeyRemovedConventions.Add(keyDiscoveryConvention);conventionSet.ForeignKeyRemovedConventions.Add(valueGeneratorConvention );conventionSet.ForeignKeyRemovedConventions.Add(foreignKeyIndexConvention);conventionSet.ForeignKeyUniquenessChangedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.ForeignKeyUniquenessChangedConventions.Add(foreignKeyIndexConvention);conventionSet.ForeignKeyOwnershipChangedConventions.Add(new NavigationEagerLoadingConvention());conventionSet.ModelBuiltConventions.Add(new ModelCleanupConvention());conventionSet.ModelBuiltConventions.Add(keyAttributeConvention);conventionSet.ModelBuiltConventions.Add(new IgnoredMembersValidationConvention());conventionSet.ModelBuiltConventions.Add(new PropertyMappingValidationConvention(Dependencies.TypeMapper));conventionSet.ModelBuiltConventions.Add(new RelationshipValidationConvention());conventionSet.ModelBuiltConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.NavigationAddedConventions.Add(backingFieldConvention);conventionSet.NavigationAddedConventions.Add(new RequiredNavigationAttributeConvention());conventionSet.NavigationAddedConventions.Add(inversePropertyAttributeConvention);conventionSet.NavigationAddedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.NavigationAddedConventions.Add(relationshipDiscoveryConvention);conventionSet.NavigationRemovedConventions.Add(relationshipDiscoveryConvention);conventionSet.IndexAddedConventions.Add(foreignKeyIndexConvention);conventionSet.IndexRemovedConventions.Add(foreignKeyIndexConvention);conventionSet.IndexUniquenessChangedConventions.Add(foreignKeyIndexConvention);conventionSet.PropertyNullabilityChangedConventions.Add(cascadeDeleteConvention);conventionSet.PrincipalEndChangedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.PropertyFieldChangedConventions.Add(keyDiscoveryConvention);conventionSet.PropertyFieldChangedConventions.Add(foreignKeyPropertyDiscoveryConvention);conventionSet.PropertyFieldChangedConventions.Add(keyAttributeConvention);conventionSet.PropertyFieldChangedConventions.Add(concurrencyCheckAttributeConvention);conventionSet.PropertyFieldChangedConventions.Add(databaseGeneratedAttributeConvention);conventionSet.PropertyFieldChangedConventions.Add(requiredPropertyAttributeConvention);conventionSet.PropertyFieldChangedConventions.Add(maxLengthAttributeConvention);conventionSet.PropertyFieldChangedConventions.Add(stringLengthAttributeConvention);conventionSet.PropertyFieldChangedConventions.Add(timestampAttributeConvention);    return conventionSet; }

我就是所有的可替换service啦。不要眼花有点多!,找着合适的用起来!

serviceCollection.AsQueryable().Where(p => p.ServiceType.ToString().StartsWith("Microsoft.EntityFrameworkCore")).Each(sd =>
{Console.WriteLine($"{sd.Lifetime.ToString().PadRight(15, ' ')}{sd.ServiceType.FullName}");
});

原文地址:http://www.cnblogs.com/calvinK/p/7234872.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324448.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上机不会做?在讲台上做做试试!

上周四班上到了sql语句的查询&#xff0c;正好临近周末&#xff0c;于是就在周末的时候布置了几个增删改查的案例让回家做做。今天随便找了几个人上黑板上做&#xff0c;本以为都没有问题了呢&#xff0c;结果做的一塌糊涂……惨&#xff0c;太惨了&#xff01;当时我就在想&am…

ASP.NET Core API 版本控制

几天前&#xff0c;我和我的朋友们使用 ASP.NET Core 开发了一个API &#xff0c;使用的是GET方式&#xff0c;将一些数据返回到客户端 APP。我们在前端进行了分页&#xff0c;意味着我们将所有数据发送给客户端&#xff0c;然后进行一些data.length操作&#xff0c;以获得item…

mybatis环境搭建步骤(含配置文件代码)

1.创建web项目2.将所需要的jar包放在项目内&#xff0c;并且build-path3.创建资源文件夹resources4.在资源文件夹中创建xml文件mybatis-config.xml,文件代码如下&#xff1a;<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUB…

多久没有给家里打过电话了?

你多久没有给家里打过电话了&#xff1f;对于我这种常年在外&#xff0c;且工作地距家直线距离都有数百公里的人来说&#xff0c;回家可是一种极大的奢侈啊。貌似自从在济南上班以来&#xff0c;平均每年也就有空回去两次&#xff0c;第一次一般都是有急事需要赶紧赶回去&#…

Feign数据压缩传输

没使用之前 使用 使用之后

漫画:删去k个数字后的最小值

转载自 漫画&#xff1a;删去k个数字后的最小值 我们来举一个栗子&#xff1a; 给定整数 541270936&#xff0c;要求删去一个数&#xff0c;让剩下的整数尽可能小。 此时&#xff0c;无论删除哪一个数字&#xff0c;最后的结果都是从9位整数变成8位整数。既然同样是8位整数&…

使用 InSpec 实现符合性即代码

法规符合性是每个企业必须面对的一个现实问题。同时&#xff0c;随着改变业界格局的新技术以及客户对数字服务的期望的出现&#xff0c;竞争压力也随之增加。各行业能否在快速交付新产品和服务的同时&#xff0c;仍然履行法规符合性义务&#xff1f; 回答是肯定的。解决方案就是…

计算机专业毕业后能做什么工作?

众所周知&#xff0c;目前比较火的专业之一莫过于计算机专业了。在这个互联网时代&#xff0c;越来越多的人选择去学习计算机专业&#xff0c;可是你知道计算机专业毕业后都有哪些岗位可选择吗&#xff1f;各个岗位的工作任务主要是什么&#xff1f;以下是对于计算机专业中各个…

什么是 binlog

转载自 什么是 binlog 引言 为什么写这篇文章? 大家当年在学MySQL的时候&#xff0c;为了能够迅速就业&#xff0c;一般是学习一下MySQL的基本语法&#xff0c;差不多就出山找工作了。水平稍微好一点的童鞋呢还会懂一点存储过程的编写&#xff0c;又或者是懂一点索引的创建…

[信息安全] 4.一次性密码 amp;amp;amp;amp; 身份认证三要素

在信息安全领域&#xff0c;一般把Cryptography称为密码&#xff0c;而把Password称为口令。日常用户的认知中&#xff0c;以及我们开发人员沟通过程中&#xff0c;绝大多数被称作密码的东西其实都是Password&#xff08;口令&#xff09;&#xff0c;而不是真正意义上的密码。…

干货!sqlserver数据库所有知识点总结整理,含代码(挺全的)

01T-SQL案例整理已知有一个表&#xff1a;该表的字段有&#xff1a;id,name,date,gradeid,email&#xff0c;表名为table_name,按要求实现下面内容。1.插入一条记录&#xff1a;insert into table_name values (1,刘世豪,2017-10-21,1,666qq.com)2.将学号是1的学生姓名修改成张…

深入源码分析Java线程池的实现原理

转载自 深入源码分析Java线程池的实现原理 程序的运行&#xff0c;其本质上&#xff0c;是对系统资源&#xff08;CPU、内存、磁盘、网络等等&#xff09;的使用。如何高效的使用这些资源是我们编程优化演进的一个方向。今天说的线程池就是一种对CPU利用的优化手段。 网上有…

“桌面日历”记录的事件居然是看某某视频……

某年某月某下午&#xff0c;正在激情澎湃的在讲台上讲课&#xff0c;忽发现医学生缓缓的将右手举起来&#xff0c;见状&#xff0c;不用想&#xff0c;他一定有问题&#xff0c;嗯……要问我。于是&#xff0c;紧走几步下去&#xff0c;问他怎么了&#xff0c;他说他的某某功能…

开源个.NetCore写的 - 并发请求工具PressureTool

本篇和大家分享的是一个 并发请求工具&#xff0c;并发往往代表的就是压力&#xff0c;对于一些订单量比较多的公司这种情况很普遍&#xff0c;也因此出现了很多应对并发的解决方案如&#xff1a;分布式&#xff0c;队列&#xff0c;数据库锁等&#xff1b; 对于没有遇到过或者…

浅析DNS域名解析过程

转载自 浅析DNS域名解析过程 对于每一个HTTP请求发起过程中&#xff0c;都有很重要的一个步骤——DNS解析&#xff0c;本篇文章将跟着DNS解析过程来分析域名是如何解析的。 一、DNS域名解析步骤 下图是DNS域名解析的一个示例图&#xff0c;它涵盖了基本解析步骤和原理。 下…