4.4 heterogeneous and multi-database access components and 4.4 heterogeneous Access Components

Source: Internet
Author: User

4.4 heterogeneous and multi-database access components and 4.4 heterogeneous Access Components

In a large system, access to multiple databases or even multiple heterogeneous databases should be allowed. For example, the form module uses mysql and the data warehouse module uses oracle. According to this goal, the Data configuration information is as follows:

 

 1     "Database": { 2       "ConnectionStrings": [ 3         { 4           "Name": "MicroStrutLibrary", 5           "ConnectionString": "Data Source=XXXX;Initial Catalog=XXXX;User Id=OperUser;Password=OperUser;MultipleActiveResultSets=true;Persist Security Info=true", 6           "ProviderName": "System.Data.SqlClient" 7         }, 8         { 9           "Name": "CMS",10           "ConnectionString": "Data Source=XXXX;Initial Catalog=XXXX;User Id=OperUser;Password=OperUser;MultipleActiveResultSets=true;Persist Security Info=true",11           "ProviderName": "System.Data.SqlClient"12         }13       ],14       "Providers": [15         {16           "Name": "System.Data.SqlClient",17           "Type": "MicroStrutLibrary.Infrastructure.Core.Data.Entity.SqlServerDbContextOptionsBuilderProvider, MicroStrutLibrary.Infrastructure.Core.Data.Entity"18         }19       ]20     }

 

Each database has a Name (which will be accessed later), ConnectionString (Database Link string), and ProviderName (provider Name ). ProviderName (provider name) describes the corresponding implementation class description TypeDescription in Providers. From the above we can see that we can set multiple databases, different databases can set different providers, that is, different database types, so as to achieve access to multiple heterogeneous databases.

For the Database Configuration Information Class DataConfigInfo, it should be very simple to implement ConfigInfo. For more information, see the configuration of replaceable sources.

In the framework, each module (such as public module, data warehouse module, form module, CMS module, and authorization and Authentication Module) corresponds to a database context DbContext. The database context points to a database, that is, to correspond to the Name attribute in the Data configuration. Our practice is to create a new DbNameAttribute and place it on DbContext to determine the Name of a specific database.

 

1 /// <summary> 2 // specify the database name feature 3 /// </summary> 4 [AttributeUsage (AttributeTargets. class, AllowMultiple = false, Inherited = false)] 5 public class DbNameAttribute: attribute 6 {7 // <summary> 8 // database Name 9 /// </summary> 10 public string Name {get; set ;} 11 12 /// <summary> 13 /// constructor 14 /// </summary> 15 /// <param name = "name"> </param> 16 public dbNameAttribute (string name) 17 {18 this. name = name; 19} 20}

 

The Name in DBNameAttribute should be set to the Name in the configuration to ensure the database corresponding to DbContext.

For example, DbContext in the public module is written as follows:

 1     [DbName("MicroStrutLibrary")] 2     public class CommonDbContext : EntityDbContext 3     { 4         public CommonDbContext(DbContextOptions<CommonDbContext> options) : base(options) 5         { 6         } 7  8         public DbSet<AccessoryInfo> Accessories { get; set; } 9 10         public DbSet<SystemParameterInfo> SystemParameters { get; set; }11         public DbSet<SystemParameterDetailInfo> SystemParameterDetails { get; set; }12     ……13     }

You will notice that CommonDbContext inherits EntityDbContext, which is the base class of the database context abstraction of the framework and inherits DbContext. This abstract class overrides the OnModelCreating method to find out all the DbSet attributes of the EntityDbContext class (for example, CommonDbContext), and forms all the DbSet generic parameter classes used by the EntityDbContext, is AccessoryInfo, SystemParameterInfo and other classes. Find all subclasses that inherit the ORMapping relationship ing base class EntityTypeConfiguration and create the ing binding relationship.

The abstract code of the relational ing base class EntityTypeConfiguration is as follows:

 

1     public abstract class EntityTypeConfiguration<T> where T: class2     {3         public void Bind(ModelBuilder modelBuilder)4         {5             InnerBind(modelBuilder.Entity<T>());6         }7 8         protected abstract void InnerBind(EntityTypeBuilder<T> builder);9     }

 

For example, the ORMapping class of the system parameter can be written:

 

1 /// <summary> 2 // system parameter ing information 3 /// </summary> 4 public class SystemParameterMapper: entityTypeConfiguration <SystemParameterInfo> 5 {6 protected override void InnerBind (EntityTypeBuilder <SystemParameterInfo> builder) 7 {8 builder. toTable ("SYSTEM_PARAMETER_INFO"); 9 10 builder. property (p => p. appCode ). hasColumnName ("APP_CODE "). isRequired (); 11 builder. property (p => p. systemParaCode ). hasColumnName ("SYSTEM_PARA_CODE "). isRequired (); 12 builder. property (p => p. systemParaName ). hasColumnName ("SYSTEM_PARA_NAME "). isRequired (); 13 builder. property (p => p. sortOrder ). hasColumnName ("SORT_ORDER "). isRequired (); 14 builder. property (p => p. remark ). hasColumnName ("REMARK"); 15 16 builder. hasKey (p => new {p. appCode, p. systemParaCode}); 17 18 builder. hasMany (p => p. detailList ). withOne (). hasForeignKey (f => new {f. appCode, f. systemParaCode }). onDelete (DeleteBehavior. cascade); 19} 20}

 

We have discussed the database configuration instructions, the specific implementation of DbContext and the implementation of ORMapping. But how can we embed the content in a program and associate DbContext with the configuration? In particular, the database Provider is written in the configuration. You cannot write services. AddDbContext <BloggingContext> (options => options. UseSqlServer (connection) in Startup? This method deviates from the original intention of using the configuration method.

To solve this problem, we will write a startup Extension Method to associate the configuration with DbContext:

 

 1         public static DbContextOptionsBuilder UseDb<TContext>(this DbContextOptionsBuilder optionsBuilder, IServiceProvider serviceProvider) where TContext : DbContext 2         { 3             DataConfigInfo config = serviceProvider.GetService<IOptions<DataConfigInfo>>().Value; 4  5             DbNameAttribute attribute = typeof(TContext).GetTypeInfo().GetCustomAttribute<DbNameAttribute>(false); 6  7             ConnectionStringSettingInfo connectionStringSetting = config.ConnectionStrings.SingleOrDefault(o => o.Name == attribute.Name); 8             ProviderSettingInfo providerSetting = config.Providers.SingleOrDefault(o => o.Name == connectionStringSetting.ProviderName); 9 10             Type providerType = Type.GetType(providerSetting.Type);11 12             DbContextOptionsBuilderProvider providerInstance = Activator.CreateInstance(providerType) as DbContextOptionsBuilderProvider;13 14             providerInstance.ConnectionStringSetting = connectionStringSetting;15             providerInstance.ProviderSetting = providerSetting;16 17             providerInstance.Build(optionsBuilder);18 19             EntityDbContext.DbContexts.TryAdd(connectionStringSetting.Name, typeof(TContext));20 21             return optionsBuilder;22         }

 

The main function of this method is: The TContext generic parameter is the implementation class of EntityDbContext, for example, CommonDbContext. The database configuration information and CommonDbContext described above are described as follows:

1. Obtain the DbNameAttribute of the current CommonDbContext class, that is, MicroStrutLibrary.

2. Obtain the connection string information of the MicroStrutLibrary database.

"Name": "MicroStrutLibrary ",

"ConnectionString": "Data Source = XXXX; Initial Catalog = XXXX; User Id = OperUser; Password = OperUser; MultipleActiveResultSets = true; Persist Security Info = true ",

"ProviderName": "System. Data. SqlClient"

3. Find the corresponding DbProvider Information

"Name": "System. Data. SqlClient ",

"Type": "MicroStrutLibrary. Infrastructure. Core. Data. Entity. SqlServerDbContextOptionsBuilderProvider, MicroStrutLibrary. Infrastructure. Core. Data. Entity"

4. Create an instance of the DbContextOptionsBuilderProvider Class Based on DbProvider information, set properties, and run the Build method of the instance. The specific class is described below.

5. append the current TContext to the static attribute DbContexts Dictionary of the EntityDbContext base class. This dictionary stores the correspondence between the database Name and TContext. Currently unavailable (this is used in the general data query function and will be introduced later ).

 

The key point is that the DbContextOptionsBuilderProvider class is provided for SQL Server, MySql, and Oracle of each type of database. The parameters of the Build method are OptionsBuilder of various database types. In the. net core class library, OptionsBuilder only needs to encapsulate them:

 

1 public abstract class completion 2 {3 public ProviderSettingInfo ProviderSetting {get; set;} 4 5 public ConnectionStringSettingInfo ConnectionStringSetting {get; set;} 6 7 public abstract void Build (DbContextOptionsBuilder optionsBuilder ); 8} 9 10 public class SqlServerDbContextOptionsBuilderProvider: dbcontextoptionsbuilder11 {12 public override void Build (DbContextOptionsBuilder optionsBuilder) 13 {14 // SQLServer 2008 R2 with version 15 optionsBuilder below. useSqlServer (this. connectionStringSetting. connectionString, ob => ob. useRowNumberForPaging (); 16 // SQLSever 2012 or later version 17 // optionsBuilder. useSqlServer (this. connectionStringSetting. connectionString); 18} 19}

 

 

The above is a specific implementation of SQLServer. However, it indicates that SQLServer 2008R2 and earlier versions do not have the offset fetch next statement and can only use the row_number () over method, therefore, optionsBuilder is used when the database is 20082008r2 or earlier. useSqlServer (this. connectionStringSetting. connectionString, ob => ob. useRowNumberForPaging (), while SQL Server 2012 and later versions use optionsBuilder. useSqlServer (this. connectionStringSetting. connectionString ).

Another note is that the SQL Server database uses datetime2 instead of datetime. Otherwise, an error is returned during conversion.

 

Cloud-oriented. net core development framework directory

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.