Zxw.Framework.NetCore: a Code First EF Core framework with unit of work and code generation
基于EF Core的Code First模式的DotNetCore快速开发框架,其中包括DBContext、IOC组件autofac和AspectCore.Injector、代码生成器(也支持DB First)、基于AspectCore的memcache和Redis缓存组件,以及基于ICanPay的支付库和一些日常用的方法和扩展,比如批量插入、更新、删除以及触发器支持,当然还有demo。欢迎提交各种建议、意见和pr~
At a glance
- What is it?
- Zxw.Framework.NetCore is a .NET rapid development framework built on EF Core that bundles a repository layer, a unit of work, dependency injection registration, a code generator that works in both Code First and DB First modes, and optional AOP caching. It suits a team that wants a full application skeleton quickly, and it does not suit one that prefers to own its data access layer outright.
- Who is it for?
- Zxw.Framework.NetCore fits a team that wants a Code First data layer, a repository abstraction, and a code generator in place within a day, and it does not fit a project that has already committed to a different repository pattern or that needs MongoDB support, since MongoDB was removed and the 7.0.0 release dropped net6.0 and net7.0.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A full application skeleton rather than a single component
Zxw.Framework.NetCore is a .NET rapid development framework built around EF Core in Code First mode. The project description is an inventory of what it contains: a DBContext, an IoC component for Autofac and for AspectCore.Injector, a code generator that also supports DB First, memcache and Redis caching components based on AspectCore, a payment library built on ICanPay, and everyday helpers such as batch insert, update, delete and trigger support, plus a demo.
That breadth is the design decision. Rather than offering a data access library, the framework offers the layer most applications end up writing anyway: repository and service abstractions over a DbContext, dependency injection wiring that scans for lifetime marker interfaces, a scaffolder for the layers above the data, and cross cutting concerns such as caching and logging handled by attributes.
The package is MIT licensed and published on NuGet under the name Zxw.Framework.NetCore, with the latest version listed as 7.0.0. A separate optional package, Zxw.Framework.AI at version 1.0.0, carries the large model provider integration and is not referenced by the main package.
The intended user is a Chinese .NET developer building a business application with a database behind it, which the documented development environment makes explicit: Visual Studio 2022, VS Code or Cursor, with the .NET SDK 8, 9 or 10. The target frameworks are net8.0, net9.0 and net10.0, and the changelog states that net6 and net7 support has been removed.
One entry point registers the lifetimes you would otherwise wire by hand
The framework's dependency injection story is deliberately blunt. The changelog entry from 2019-12-17 records the addition of a single entry point extension method, AddCoreX, and states that the method by default enables injection of classes implementing ISingletonDependency, IScopedDependency and ITransientDependency, three different lifetime interfaces, along with AddHttpContextAccessor and AddDataProtection. If automatic injection is wanted, a class implements whichever of the three interfaces suits it, and nothing else is required.
So the registration convention is marker interfaces rather than assembly scanning plus attributes, and the developer chooses the lifetime by choosing the interface. The same entry point is what wires the framework's own services, which is why it takes a configuration callback.
services.AddCoreX(config=> { })The default container is Microsoft.Extensions.DependencyInjection, with Autofac available as an option, and AspectCore available for AOP. The DI choice is therefore not imposed. The same section of the changelog notes that AspectCore was upgraded to 2.0.0 and that a session context, WebContext, was added, which later became scoped, reading the current HttpContext from IHttpContextAccessor on each use rather than capturing it.
The 7.0.0 release tightened this further. The repository, service and web context lifetimes are now Scoped, and the changelog says this is because Transient and Singleton were being used to carry request state dependencies, which is a correctness fix rather than a style preference.
A code generator that reads the model or reads the database
The code generator is the part of the framework that saves the most typing, and it is genuinely bidirectional. The changelog entry from 2019-08-11 records a refactor that split the generator into Code First and DB First modes, and the documented usage shows both.
dbContext.CodeFirst().GenerateAll(ifExsitedCovered:true);
dbCOntext.DbFirst().GenerateAll(ifExsitedCovered:true);The two modes differ in the direction of travel. Code First starts from the entity model and generates the other layers, while DB First starts from existing database tables and generates those layers. The ifExsitedCovered flag controls whether existing files are overwritten, so regenerating after a schema change does not destroy hand edits in unrelated files.
The generator is not enabled by default. It is switched on with an explicit call in the service registration, using a CodeGeneratorOption instance.
services.UseCodeGenerator(new CodeGeneratorOption());The same changelog entry records that support for generating API controllers was added at the time, which tells you what the generated output is aimed at: a layered CRUD application with a web API on top, not a domain model design.
A unit of work for the case where one transaction spans two repositories
The 7.0.0 release added IUnitOfWork and EfUnitOfWork, and the changelog explains why in the same line: with DbContextOption.AutoSaveChanges set to false, changes have to be committed explicitly so that a transaction can span repositories.
var option = new DbContextOption
{
ConnectionString = "...",
AutoSaveChanges = false
};
// ...
await repoA.AddAsync(a);
await repoB.AddAsync(b);
await uow.SaveChangesAsync(); // IUnitOfWorkAutoSaveChanges defaults to true for compatibility with the old behaviour, so an existing application keeps working without change. The unit of work is opt in, and it is the answer to the case where two repositories write to different aggregates that must commit together.
Two other data access fixes in the same release are worth noting because they change what the repository does rather than how it is called. The repository constructor no longer calls EnsureCreated, and the changelog tells production environments to use migrations instead, which is the correct behaviour for a shipped application but does mean a fresh deployment now needs a migration step that it did not need before. And the repository Dispose method no longer releases the shared DbContext, since that is managed by the DI scope, which is what makes the scoped lifetime safe.
Provider coverage that shifted with .NET 10
The database list is broad, and the 7.0.0 notes are honest about where it is uneven. SQL Server, MySQL, Sqlite, InMemory, PostgreSQL and Oracle are listed as supported, while MongoDB is marked as removed, and the 2022-11-20 changelog entry records the removal of MongoDB support at that time as well, alongside net7.0 compatibility and the deprecation of HttpRequestHelper in favour of HttpClient.
MySQL has two providers depending on the target framework. The changelog states that for net8 and net9 the driver is Pomelo, and for net10 it is MySql.EntityFrameworkCore, with the reason given as Pomelo 10 not having been released, and a note that the project will switch back once Pomelo officially supports EF10. The consequence for an application is that a bulk insert call behaves differently on net10, where BulkInsert degrades to AddRange.
Dependencies are aligned per target framework, with EF Core, Npgsql, Oracle and Z.EntityFramework.Plus majors matched to the TFM, and the release also removed a duplicate DotNetCore.NPOI reference along with the discontinued Jil and StackExchange.Redis.Extensions.JilCore packages.
The JSON change is the one most likely to affect an existing application. Jil was dropped, and JsonConvertor now uses System.Text.Json, with the old Jil.Options parameter replaced by JsonSerializerOptions, and DeserializeDynamic removed. Any code that relied on dynamic deserialisation has to be rewritten, not recompiled.
AOP caching, an LLM provider, and a framework that is still moving
Caching is handled through an AOP middleware, AspectCore.Extensions.Cache, with a separate repository, and the changelog records a 2019-09-15 refactor that unified the AOP cache onto a single CachedAttribute, and a 2019-04-25 change setting the default cache key format to namespace, class, method and a hash of the parameter values. Logging goes through log4net, though the README recommends that business code prefer the standard ILogger<T> abstraction.
The optional AI package is the newest addition. It registers OrcaRouter as a built in LLM provider, configured through a provider descriptor in providers/orcarouter.json, and enabled with a call that sets the API key, a default model of orcarouter/auto, and a list of fallback models.
services.AddOrcaRouter(o =>
{
o.DefaultModel = "orcarouter/auto";
o.FallbackModels = new[] { "openai/gpt-4o-mini", "deepseek/deepseek-chat" };
});The main package does not reference a large model, and the AI package is installed on demand, which keeps the core framework free of that dependency. The .env.example file shows the ORCAROUTER_API_KEY and optional base URL and model overrides.
The maintenance picture is mixed in a way worth weighing. The last push was on 2026-08-31 and the 7.0.0 release entry is dated 2026-08-19, so the current version is recent, but the repository has no GitHub releases, so the changelog in the README is the release history. The roadmap section plans to split the framework into optional packages, Abstractions, EFCore with per database providers, Caching, AspNetCore and CodeGenerator, while keeping the Zxw.Framework.NetCore meta package for existing references. The AI package is the first piece of that split already done, which means the package layout you depend on today may still move.
Editorial conclusion
Zxw.Framework.NetCore fits a team that wants a Code First data layer, a repository abstraction, and a code generator in place within a day, and it does not fit a project that has already committed to a different repository pattern or that needs MongoDB support, since MongoDB was removed and the 7.0.0 release dropped net6.0 and net7.0. Before adopting it, read the 7.0.0 breaking change list in the changelog, because the repository, service and web context lifetimes changed to Scoped, the JSON stack moved from Jil to System.Text.Json, and the repository constructor no longer calls EnsureCreated, so production schemas have to come from migrations.
Frequently asked questions
How do I install Zxw.Framework.NetCore?
The package is on NuGet at version 7.0.0, installed with the Install-Package Zxw.Framework.NetCore -Version 7.0.0 command or by running dotnet add package Zxw.Framework.NetCore --version 7.0.0. The optional AI package Zxw.Framework.AI is version 1.0.0 and is installed separately.
Which databases does Zxw.Framework.NetCore support?
The documented list is SQL Server, MySQL, Sqlite, InMemory, PostgreSQL and Oracle, with MongoDB removed. MySQL uses Pomelo on net8 and net9 and MySql.EntityFrameworkCore on net10 while Pomelo 10 is unavailable, where BulkInsert degrades to AddRange.
What changed in the breaking 7.0.0 release of Zxw.Framework.NetCore?
The target frameworks became net8.0, net9.0 and net10.0 with net6.0 and net7.0 removed, the repository, service and web context lifetimes became Scoped, the JSON layer moved from Jil to System.Text.Json with DeserializeDynamic removed, a unit of work was added, the repository constructor stopped calling EnsureCreated, and a new SqlIdentifier type was added to validate dynamic SQL identifiers.
How does the Zxw.Framework.NetCore code generator work?
It works in two directions, Code First from the entity model and DB First from existing database tables, both through a GenerateAll call with an ifExsitedCovered flag that controls overwriting of existing files. It has to be enabled explicitly with services.UseCodeGenerator(new CodeGeneratorOption()).
How does Zxw.Framework.NetCore register services in the container?
A single AddCoreX extension method enables automatic injection of classes implementing ISingletonDependency, IScopedDependency or ITransientDependency, and also registers AddHttpContextAccessor and AddDataProtection. Microsoft.Extensions.DependencyInjection is the default container, with Autofac and AspectCore available as options.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/victortzeng-zxw-framework-netcore)Was this useful?