Introduce
Protagonist of this issue :
ShardingCorea ef-core High performance 、 Lightweight solution for reading and writing separation of tables and Libraries , With zero dependency 、 Zero learning cost 、 Zero business code intrusionWTMWalkingTec.Mvvm frame ( abbreviation WTM) Is based on .net core The rapid development framework of . Support Layui( The front and rear ends do not separate ), React( Fore and aft end separation ),VUE( Fore and aft end separation ), Built in code generator , Maximize development efficiency , It's an efficient development tool .
ShardingCore The latest version has great performance optimization for routing Expression Change to custom RouteExpression In addition to the Compile Performance loss
I'm not efcore What do I do
There must be some friends here who want to ask if they are not efcore Of , I am sure to tell you that I have and adapt to all ADO.NET Include sqlhelperShardingConnector Based on a ado.net At present, the high-performance sub table and sub database solutions based on demo Case study , This framework you can think of as .Net Version of ShardingSphere But at present, only ShardingSphere-JDBC, In the future, I will realize ShardingSphere-Proxy I hope you all .Neter Pay more attention to
background
I posted a blog before .Net Dynamic processing of tables and databases Here is a message from a little friend , I hope I can support you WTM frame . I thought I was confident in my own frame , And I've been right before abpvnex and furion And so on , In principle, as long as you are efcore So basically, it can support , So I started with the following attitude , The first conclusion is that it can support , I don't know whether it is perfect or not because I don't use this framework very much. I don't know whether it is a perfect fit .
principle
ShardingCore
ShardingCore The overall architecture of is a shell dbcontext Take more than one dbcontext, shell dbcontext Do not add, delete, modify or query , From the inside dbcontext Do it yourself , Because efcore An object of the corresponding table is restricted by . Let's put the shell here dbcontext Referred to as shellDbContext, Executive dbcontext be called executorDbContext, about ShardingCore Another requirement is to initialize the startup Start(),Start() Internal needs IServiceProvider To get DbContext, So the whole framework is inseparable ioc, Then you need to start dependency injection DbContext, And because dependency injection can only allow a single constructor if it is the default . This is it. ShardingCore What should be paid attention to in compatible use .
WTM
WTM I'm not very familiar here , It took about half an hour to about an hour , Read the code , I have learned about the implementation ,DbContext The creation of is implemented by a separate constructor , Default by DbContext Internal method of OnConfiguring(DbContextOptionsBuilder optionsBuilder) To initialize , The frame will DbContext The abstraction becomes IDataContext Interface , Frame default IDataContext Interface default dependency injection is NullDbContext If you need to use, you will call the constructor by reflection. The parameter is CS The one of type . Holistic efcore You can basically understand some of the processing on the through debugging code and viewing the source code
Start connecting
Create project
So first of all, let's go through WTM Generate a simple project for scaffolding , This generates a mvc Project .
Add dependency
add to ShardingCore rely on , need x.5.0.6+ edition ,x representative efcore Version of
Install-Package ShardingCore -Version 6.5.0.6
Add an abstract sub table DbContext
This way and AbpVNext It's the same when you inherit , because c# Multiple inheritance is not supported , Fortunately ShardingCore It is interface dependency, and there is no implementation dependency, so any framework can be compatible .
public abstract class AbstractShardingFrameworkContext:FrameworkContext, IShardingDbContext, ISupportShardingReadWrite
{
protected IShardingDbContextExecutor ShardingDbContextExecutor
{
get;
}
public AbstractShardingFrameworkContext(CS cs)
: base(cs)
{
ShardingDbContextExecutor =
(IShardingDbContextExecutor)Activator.CreateInstance(
typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this);
IsExecutor = false;
}
public AbstractShardingFrameworkContext(string cs, DBTypeEnum dbtype)
: base(cs, dbtype)
{
ShardingDbContextExecutor =
(IShardingDbContextExecutor)Activator.CreateInstance(
typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this);
IsExecutor = false;
}
public AbstractShardingFrameworkContext(string cs, DBTypeEnum dbtype, string version = null)
: base(cs, dbtype, version)
{
ShardingDbContextExecutor =
(IShardingDbContextExecutor)Activator.CreateInstance(
typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this);
IsExecutor = false;
}
public AbstractShardingFrameworkContext(DbContextOptions options) : base(options)
{
var wrapOptionsExtension = options.FindExtension<ShardingWrapOptionsExtension>();
if (wrapOptionsExtension != null)
{
ShardingDbContextExecutor =
(IShardingDbContextExecutor)Activator.CreateInstance(
typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this);
}
IsExecutor = wrapOptionsExtension == null;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (this.CSName!=null)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSharding<DataContext>();
}
}
/// <summary>
/// Read write separation priority
/// </summary>
public int ReadWriteSeparationPriority
{
get => ShardingDbContextExecutor.ReadWriteSeparationPriority;
set => ShardingDbContextExecutor.ReadWriteSeparationPriority = value;
}
/// <summary>
/// Whether to use read-write separation
/// </summary>
public bool ReadWriteSeparation
{
get => ShardingDbContextExecutor.ReadWriteSeparation;
set => ShardingDbContextExecutor.ReadWriteSeparation = value;
}
/// <summary>
/// Whether it is the real executor
/// </summary>
public bool IsExecutor { get;}
public DbContext GetDbContext(string dataSourceName, bool parallelQuery, IRouteTail routeTail)
{
return ShardingDbContextExecutor.CreateDbContext(parallelQuery, dataSourceName, routeTail);
}
/// <summary>
/// Create generic based on objects dbcontext
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
public DbContext CreateGenericDbContext<TEntity>(TEntity entity) where TEntity : class
{
return ShardingDbContextExecutor.CreateGenericDbContext(entity);
}
public IVirtualDataSource GetVirtualDataSource()
{
return ShardingDbContextExecutor.GetVirtualDataSource();
}
public override EntityEntry Add(object entity)
{
if (IsExecutor)
base.Add(entity);
return CreateGenericDbContext(entity).Add(entity);
}
public override EntityEntry<TEntity> Add<TEntity>(TEntity entity)
{
if (IsExecutor)
return base.Add(entity);
return CreateGenericDbContext(entity).Add(entity);
}
public override ValueTask<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
{
if (IsExecutor)
return base.AddAsync(entity, cancellationToken);
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
}
public override ValueTask<EntityEntry> AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken())
{
if (IsExecutor)
return base.AddAsync(entity, cancellationToken);
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
}
private Dictionary<DbContext, IEnumerable<TEntity>> AggregateToDic<TEntity>(IEnumerable<TEntity> entities) where TEntity:class
{
return entities.Select(o =>
{
var dbContext = CreateGenericDbContext(o);
return new
{
DbContext = dbContext,
Entity = o
};
}).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity));
}
public override void AddRange(params object[] entities)
{
if (IsExecutor)
{
base.AddRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.AddRange(aggregateKv.Value);
}
}
public override void AddRange(IEnumerable<object> entities)
{
if (IsExecutor)
{
base.AddRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.AddRange(aggregateKv.Value);
}
}
public override async Task AddRangeAsync(params object[] entities)
{
if (IsExecutor)
{
await base.AddRangeAsync(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
await aggregateKv.Key.AddRangeAsync(aggregateKv.Value);
}
}
public override async Task AddRangeAsync(IEnumerable<object> entities, CancellationToken cancellationToken = new CancellationToken())
{
if (IsExecutor)
{
await base.AddRangeAsync(entities, cancellationToken);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
await aggregateKv.Key.AddRangeAsync(aggregateKv.Value,cancellationToken);
}
}
public override EntityEntry<TEntity> Attach<TEntity>(TEntity entity)
{
if (IsExecutor)
return base.Attach(entity);
return CreateGenericDbContext(entity).Attach(entity);
}
public override EntityEntry Attach(object entity)
{
if (IsExecutor)
return base.Attach(entity);
return CreateGenericDbContext(entity).Attach(entity);
}
public override void AttachRange(params object[] entities)
{
if (IsExecutor)
{
base.AttachRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.AttachRange(aggregateKv.Value);
}
}
public override void AttachRange(IEnumerable<object> entities)
{
if (IsExecutor)
{
base.AttachRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.AttachRange(aggregateKv.Value);
}
}
public override EntityEntry<TEntity> Entry<TEntity>(TEntity entity)
{
if (IsExecutor)
return base.Entry(entity);
return CreateGenericDbContext(entity).Entry(entity);
}
public override EntityEntry Entry(object entity)
{
if (IsExecutor)
return base.Entry(entity);
return CreateGenericDbContext(entity).Entry(entity);
}
public override EntityEntry<TEntity> Update<TEntity>(TEntity entity)
{
if (IsExecutor)
return base.Update(entity);
return CreateGenericDbContext(entity).Update(entity);
}
public override EntityEntry Update(object entity)
{
if (IsExecutor)
return base.Update(entity);
return CreateGenericDbContext(entity).Update(entity);
}
public override void UpdateRange(params object[] entities)
{
if (IsExecutor)
{
base.UpdateRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.UpdateRange(aggregateKv.Value);
}
}
public override void UpdateRange(IEnumerable<object> entities)
{
if (IsExecutor)
{
base.UpdateRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.UpdateRange(aggregateKv.Value);
}
}
public override EntityEntry<TEntity> Remove<TEntity>(TEntity entity)
{
if (IsExecutor)
return base.Remove(entity);
return CreateGenericDbContext(entity).Remove(entity);
}
public override EntityEntry Remove(object entity)
{
if (IsExecutor)
return base.Remove(entity);
return CreateGenericDbContext(entity).Remove(entity);
}
public override void RemoveRange(params object[] entities)
{
if (IsExecutor)
{
base.RemoveRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.RemoveRange(aggregateKv.Value);
}
}
public override void RemoveRange(IEnumerable<object> entities)
{
if (IsExecutor)
{
base.RemoveRange(entities);
return;
}
var aggregateToDic = AggregateToDic(entities);
foreach (var aggregateKv in aggregateToDic)
{
aggregateKv.Key.RemoveRange(aggregateKv.Value);
}
}
public override int SaveChanges()
{
if (IsExecutor)
return base.SaveChanges();
return this.SaveChanges(true);
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
if (IsExecutor)
return base.SaveChanges(acceptAllChangesOnSuccess);
//ApplyShardingConcepts();
int i = 0;
// If it is an internal affair, it will be digested internally
if (Database.AutoTransactionsEnabled&&Database.CurrentTransaction==null&&ShardingDbContextExecutor.IsMultiDbContext)
{
using (var tran = Database.BeginTransaction())
{
i = ShardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess);
tran.Commit();
}
}
else
{
i = ShardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess);
}
return i;
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
if (IsExecutor)
return base.SaveChangesAsync(cancellationToken);
return this.SaveChangesAsync(true, cancellationToken);
}
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken())
{
if (IsExecutor)
return await base.SaveChangesAsync(acceptAllChangesOnSuccess,cancellationToken);
//ApplyShardingConcepts();
int i = 0;
// If it is an internal affair, it will be digested internally
if (Database.AutoTransactionsEnabled && Database.CurrentTransaction==null && ShardingDbContextExecutor.IsMultiDbContext)
{
using (var tran = await Database.BeginTransactionAsync(cancellationToken))
{
i = await ShardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
await tran.CommitAsync(cancellationToken);
}
}
else
{
i = await ShardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
return i;
}
public override void Dispose()
{
if (IsExecutor)
{
base.Dispose();
}
else
{
ShardingDbContextExecutor.Dispose();
base.Dispose();
}
}
public override async ValueTask DisposeAsync()
{
if (IsExecutor)
{
await base.DisposeAsync();
}
else
{
await ShardingDbContextExecutor.DisposeAsync();
await base.DisposeAsync();
}
}
public Task RollbackAsync(CancellationToken cancellationToken = new CancellationToken())
{
return ShardingDbContextExecutor.RollbackAsync(cancellationToken);
}
public Task CommitAsync(CancellationToken cancellationToken = new CancellationToken())
{
return ShardingDbContextExecutor.CommitAsync(cancellationToken);
}
public void NotifyShardingTransaction()
{
ShardingDbContextExecutor.NotifyShardingTransaction();
}
public void Rollback()
{
ShardingDbContextExecutor.Rollback();
}
public void Commit()
{
ShardingDbContextExecutor.Commit();
}
}
To put it simply, this side has realized WTM All constructors for , because ShardingCore Native needs DbContextOption, Of course, it can also support the customization of implementation classes DbContext, If... Is used in the constructor DbContextOption Then it is by dependency injection or ShardingCore Created DbContext, The rest are all WTM Created , Therefore, all the constructors here need to be implemented and the rest of the constructors are directly set to ShellDbContext
Again because WTM The default creation will assign values CSName Therefore, it is necessary to carry out follow-up UseSharding Handling this is ShardingCore in the light of ShellDbContext Must deal with
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (this.CSName!=null)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSharding<DataContext>();
}
}
Realization DataContext
It's very simple. You only need to inherit the abstract class and implementation IShardingTableDbContext Interface can , Only by implementing this interface can tables be divided. Otherwise, only databases can be divided
public class DataContext : AbstractShardingFrameworkContext,IShardingTableDbContext
{
}
Write custom DbContext establish
because WTM Framework of the DbContext It has multiple constructors, so it needs to be customized , from ShardingCore Provide
The code is actually very simple, that is, how to create a DbContext, because ShardingCore The default verifier can only have one constructor and the constructor can only be DbContextOptions perhaps DbContextOptions<>
public class WTMDbContextCreator<TShardingDbContext>:IDbContextCreator<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
public DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions)
{
var context = new DataContext((DbContextOptions<DataContext>)shardingDbContextOptions.DbContextOptions);
context.RouteTail = shardingDbContextOptions.RouteTail;
return context;
}
}
Write the sub table test class
public class Todo
{
public string Id { get; set; }
public string Name { get; set; }
}
And then again DbContext Make a simple setup
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Do you use dbset It's OK, too
modelBuilder.Entity<Todo>(e =>
{
e.HasKey(o => o.Id);
e.ToTable(nameof(Todo));
});
}
Add a sub table route
public class TodoRoute:AbstractSimpleShardingModKeyStringVirtualTableRoute<Todo>
{
public TodoRoute() : base(2, 10)
{
}
public override void Configure(EntityMetadataTableBuilder<Todo> builder)
{
builder.ShardingProperty(o => o.Id);
}
}
StartUp
Then comes the exciting time , First we said ShardingCore Need dependency injection , Because DbContext Is a multiple constructor
services.AddScoped<DataContext>(sp =>
{
var dbContextOptionsBuilder = new DbContextOptionsBuilder<DataContext>();
dbContextOptionsBuilder.UseMySql(
"server=127.0.0.1;port=3306;database=shardingTest;userid=root;password=root;",
new MySqlServerVersion(new Version()));
dbContextOptionsBuilder.UseSharding<DataContext>();
return new DataContext(dbContextOptionsBuilder.Options);
});
Note that dependency injection gets ShellDbContext So we need to do it UseSharding()
Then we need to configure ShardingCore
services.AddShardingConfigure<DataContext>()
.AddEntityConfig(o =>
{
o.CreateShardingTableOnStart = true;
o.EnsureCreatedWithOutShardingTable = true;
o.AddShardingTableRoute<TodoRoute>();
})
.AddConfig(o =>
{
o.AddDefaultDataSource("ds0",
"server=127.0.0.1;port=3306;database=shardingTest;userid=root;password=root;");
o.ConfigId = "c1";
o.UseShardingQuery((conn, build) =>
{
build.UseMySql(conn, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
});
o.UseShardingTransaction((conn,build)=>
build.UseMySql(conn,new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger)
);
o.ReplaceTableEnsureManager(sp => new MySqlTableEnsureManager<DataContext>());
}).EnsureConfig();
The configuration here is ShardingCore It is very simple to query documents or past blogs
At this time, someone has to say why not use it AddShardingDbContext Because multiple constructors do not support manual processing by default .
Replace ShardingCore Of DbContext establish , What we just wrote
services.Replace(ServiceDescriptor.Singleton<IDbContextCreator<DataContext>, WTMDbContextCreator<DataContext>>());
And then replace WTM Of IDataContext
// This is a WTM The default needs to be replaced
//services.TryAddScoped<IDataContext, NullContext>();
services.Replace(ServiceDescriptor.Scoped<IDataContext>(sp =>
{
return sp.GetService<DataContext>();
}));
Then start initialization ShardingCore
app.ApplicationServices.GetRequiredService<IShardingBootstrapper>().Start();
Write tests demo
public async Task<ActionResult> Login(LoginVM vm)
{
var dataContext = Wtm.DC;
var todos = new List<Todo>();
for (int i = 0; i < 100; i++)
{
var todo = new Todo();
todo.Id = Guid.NewGuid().ToString("n");
todo.Name = todo.Id;
todos.Add(todo);
}
await dataContext.Set<Todo>().AddRangeAsync(todos);
await dataContext.SaveChangesAsync();
var listAsync = await dataContext.Set<Todo>().Take(2).ToListAsync();
....
}
Startup and operation

Perfect for creating sub tables and inserting queries completely and using WTM equally
Last, last
demo Address https://github.com/xuejmnet/ShardingWTM
You've seen it here. Are you sure you don't want to order star Or like it , a .Net Have to learn the sub database and sub table solution , It is simply understood as sharding-jdbc stay .net And support more features and better data aggregation , With native performance 97%, And no business intrusion , Support all non segmented efcore Native query
- github Address https://github.com/xuejmnet/sharding-core
- gitee Address https://gitee.com/dotnetchina/sharding-core
NetCore frame WTM More related articles about the implementation of sub tables and sub databases of
- .NETCore Sub table and sub database are supported 、 The universal separation of reading and writing Repository
First of all, this article is not a headline party , The library I'm talking about is FreeSql.Repository, It serves as an extension to the common repository layer functionality , Interface specification reference abp vnext Definition , The basic storage layer is realized (CURD). install d ...
- [NewLife.XCode] Table depots ( 10 billion level big data storage )
NewLife.XCode Is a 15 Open source data middleware with a history of years , Support netcore/net45/net40, By the new life team (2002~2019) Development completed and maintained so far , hereinafter referred to as XCode. The whole series of tutorials will be a lot of ...
- Table and database solutions (mycat,tidb,shardingjdbc)
Recently, the company has a demand for sub tables and sub databases , So sort out the solutions of tables and databases and related problems . 1.sharding-jdbc(sharding-sphere) advantage : 1. Can be applied to any based on java Of ORM frame , Such as :JPA. ...
- .NET ORM Table depots 【 to the end 】 How do you do it? ?
Theoretical knowledge table - On the surface , Is to divide a table into N Multiple little watches , Every little watch is a perfect one . The data is stored in the sub table , The master watch is just a shell , Access data occurs in one sub table . After splitting tables, the concurrency of a single table is improved ...
- efcore Analysis of the principle of dividing tables and databases
ShardingCore ShardingCore Easy to use . Simple . High performance . Universality , Is an extension for efcore Extension solution of sub table and sub database under Ecology , Support efcore2+ All versions of , Support efcore2+ All data for ...
- Abp VNext Table depots , Reject manual , We want to happy coding
Abp VNext Table depots ShardingCore ShardingCore Easy to use . Simple . High performance . Universality , Is an extension for efcore Extension solution of sub table and sub database under Ecology , Support efcore2+ All versions of , ...
- Furion I also want to happy coding
Furion Integration of tables and databases ShardingCore ShardingCore ShardingCore Easy to use . Simple . High performance . Universality , Is an extension for efcore Extension solution of sub table and sub database under Ecology , Support efco ...
- .Net Remove the high-performance sub table and sub library components - Connection mode principle
ShardingCore ShardingCore a ef-core High performance . Lightweight solution for reading and writing separation of tables and Libraries , With zero dependency . Zero learning cost . Zero business code intrusion . Github Source Code help ...
- .Net Next, you have to look at the sub table and sub database solution - Multi field slicing
.Net Next, you have to look at the sub table and sub database solution - Multi field slicing Introduce Protagonist of this issue :ShardingCore a ef-core High performance . Lightweight solution for reading and writing separation of tables and Libraries , With zero dependency . Zero learning cost . Zero business code intrusion ...
- efcore Use ShardingCore Implement multi tenancy under separate tables and databases
efcore Use ShardingCore Implement multi tenancy under separate tables and databases Introduce Protagonist of this issue :ShardingCore a ef-core High performance . Lightweight solution for reading and writing separation of tables and Libraries , With zero dependency . Zero learning cost . Zero business ...
Random recommendation
- JUC In retrospect -Semaphore Underlying implementation and principles
1. Control the number of concurrent threads Semaphore Semaphore( Semaphore ) Is used to control the number of threads accessing a specific resource at the same time , It works by coordinating threads , Ensure the rational use of public resources . Threads can pass through acquire() Method to obtain the value of the semaphore ...
- SQL Server Database learning notes -E-R Model
Entity (Entities) contact (Relationships) Model abbreviation E-R The model is also called E-R Method , By P.P.Chen On 1976 First proposed in . There is also a key element Attributes- attribute , It provides data that is not subject to any database ...
- FSG Compression shell and ImportREC Use - Shelling 05
FSG Compression shell and ImportREC Use - Shelling 05 Let programming change the world Change the world by program FSG This shell is a little unruly , Nima, you said that you can achieve the compression function with a compression shell ...
- JavaScript Simple ....
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【 principle 、 command 】Git The basic principle 、 And Svn The difference between 、 command
One .Git What is it? ? Git It is the most advanced distributed version control system in the world . working principle / technological process :Workspace: work area Index / Stage: Temporary storage area Repository: Warehouse area ( Or local warehouse )Remote ...
- thinkphp On Alibaba cloud nginx.config To configure
# For more information on configuration, see: # * Official English Documentation: http://nginx.org/e ...
- Oracle Diagnostic tools - ORA-4030 Troubleshooting Tool
ORA-4030 explain Oracle Server process (server process) Can't on operating system (OS) Allocate enough memory on the . Lead to ORA-4030 The main reasons are : - Not enough physical memory -OS kernel/ ...
- IIS7 Remove the pseudo static in the above version index.php Method
1, As a result of iis7 Version above httpd.ini The file will no longer be parsed , Put the following xml File copy to web.config In the file of , Then put it in the root directory of the website . <?xml version="1.0 ...
- @WebServlet
Write it well Servlet after , Next, let me tell you Web The container is about this Servlet Some information . stay Servlet 3.0 in , You can use dimensions (Annotation) To tell which containers Servlet Will provide services and additional information . ...
- jquery.chosen.js Drop down selection box beautify plug-in project instance
Due to the previous use of bootstrap-select Plug ins are built on bootstrap Based on , When it's actually used in a project , With the ace-admin( be based on bootstrap) There are style conflicts , Causes the style of the drop-down box to change ...









