Casual Notes on Cross-Platform Framework AspNetCore Development Practice
Preface Recently I've been learning by doing and have gotten a preliminary handle on AspNetCore development, familiarizing myself a bit with the MVC stack. Because I hadn't used it for independent projects before—always collaborating with others—we used a frontend-backend split, and I only did WebApi, and they were very small projects (course-assignment level). In production I probably used Python's Django framework the most. This time I rewrote a previous Django project with AspNetCore, and performance improved quite a bit. C#'s performance is no joke, and AspNetCore's performance is also quite
目录9 个章节
Preface

Recently I've been learning by doing and have gotten a preliminary handle on AspNetCore development, familiarizing myself a bit with the MVC stack. Because I hadn't used it for independent projects before—always collaborating with others—we used a frontend-backend split, and I only did WebApi, and they were very small projects (course-assignment level). In production I probably used Python's Django framework the most. This time I rewrote a previous Django project with AspNetCore, and performance improved quite a bit. C#'s performance is no joke, and AspNetCore's performance is quite good too—it's on the leaderboards (WebApi). Although MVC doesn't make the rankings, its performance still leaves Django in the dust. Django requires all kinds of performance optimizations before every production deploy—terrifying. Then again, performance that's too good isn't great either; the company might think my workload isn't full enough (runs away)
ok, since this is a ramble, I don't need to organize everything neatly. I'll casually list a few aspects and chat about them compared to other frameworks (Django, Spring, and the like)~ Since I'm a beginner, if my understanding of various concepts is off, please correct me, experts, and everyone is welcome to discuss haha
Dependency Injection

For me, used to writing Django, dependency injection was something I rarely used before. I just searched and found a discussion on Stack Overflow (Why is IoC / DI not common in Python?) that explained it well and enlightened me a bit. Portal: https://stackoverflow.com/questions/2461702/why-is-ioc-di-not-common-in-python
Python modules are singletons by nature, which is who-knows-how-much better than Java, a language where even how many ways there are to implement the singleton pattern can show up in interview questions. C# is much better—it has static classes—but in development you still register as Singleton in the IoC container to achieve a singleton~
There's a vivid analogy for dependency injection: treating a static language like a dynamic scripting language. At startup you dump a bunch of stuff into the IoC container; when you need something you tell the container what you want and it generates it for you. And the stuff in the container can import other dependencies, layer upon layer of mutual dependencies. If something goes wrong while the framework is running, troubleshooting is painful hhh. You also have to watch out for circular dependencies and other issues caused by design problems. So I feel Django is still well designed, and productivity is truly high. I haven't used other web frameworks much; besides AspNetCore and Django, I've used traditional Spring, Beego, and MVC frameworks in other niche languages (I even used dart to write backends, for all the good it did). When I have time I'll try emerging ones like Vert.x and WebFlux—should be pretty fun~
As far as IoC and DI go, AspNetCore and Spring are similar—similar features, similar usage, hhh. Writing it definitely isn't as fluid as Python, but why do I still use something like AspNetCore? Because writing in a statically typed language feels great. Drf is especially fast for writing APIs, but you basically write by guessing, hahaha—that description feels pretty accurate. Recently FastApi looks pretty good; it's said to have 100% type annotations, so you can write Python as if it were a statically typed language. But that kind of framework is too new, hasn't been validated by the market, and is hard to use in production…
ORM

Database operations are the core of web frameworks nowadays (or is that wrong?). I don't know, anyway web development is basically CRUD, so dealing with databases all day is definitely right, so ORM is important. A well-designed, easy-to-use ORM can cut a lot of work. A big reason Django is popular is that its ORM is powerful and easy to use—this should also be one of the advantages of dynamic languages.
- efcore
- FreeSQL
- Chloe
- Dapper
- Lightweight ORM Framework—Part 1: Quick Start with Dapper: https://www.cnblogs.com/huangxincheng/p/5828470.html
On the .NetCore platform, of other ORMs I've only used EF Core and Chloe (official site: https://github.com/shuxinqin/Chloe). Chloe is also a Chinese-made ORM, quite convenient to use, but it doesn't support database migrations, so you can't generate database tables from code, which is a bit annoying. EFCore is Microsoft's official ORM, so of course it's good to use, and it supports database migrations, which is very convenient. I can't really summarize other features because I haven't used it deeply and don't have any particular impressions.
For this project I chose the Chinese-made FreeSQL. The reason is I happened to see the author's self-promoting article on cnblogs, thought it looked pretty good, and decided to try it. It really is quite nice to use—you can establish a database connection in a single lightweight line, or have all kinds of rich features like EFCore, and it also supports DB First, which is very comfortable. This time, because I was migrating a Django project to AspNetCore, I planned to try the original database first, and after FreeSQL's DB First it actually worked beautifully, which strengthened my confidence to keep using it, haha (though I ran into a lot of pitfalls later, mostly about many-to-many relationships—spoiled by Django ORM)
FreeSQL official docs: https://github.com/dotnetcore/FreeSql/wiki
From my experience, FreeSQL's handling of foreign keys (one-to-many, many-to-one), many-to-many, and one-to-one relationships is decent, through "navigation properties," should be similar to EFCore. But when defining a Model, if there's a foreign key you also have to define an extra field to store the Id, which feels a bit inhumane. EFCore doesn't need that—you just reference the object, and after migration it shows up in the table as a foreign key Id. However, FreeSQL uses soft foreign keys: references are references, all relationships are handled in code, no foreign keys are generated in the database. This has its benefits too, you could even call it an advantage—sometimes maintaining table integrity constraints is a bit of a hassle hhh
Reference article: What Problems Can .NET ORM Navigation Properties Actually Solve? https://www.cnblogs.com/kellynic/p/13575053.html
Then I also briefly compared Kotlin's Ktorm, which is also an excellent ORM. Last time I tried it a bit too, pretty nice, except it has no migration feature so it can't auto-create tables. Ktorm's usage experience is similar to EFCore—likewise you just reference foreign keys directly, no need to leave an Id field like FreeSQL. Each has its pros and cons… I won't go into it
PS: After I complained about Ktorm in a previous article, the author saw it and came over to walk me through writing code (runs away). Some of the pitfalls really weren't the framework's problem—I was just too noob…
Database

I use SQLite for the database. For small projects I use it for everything anyway—good performance, convenient to deploy. There's a write lock, but for a system used by just a few people, who needs a bicycle?
- Notes on a SQLite Performance Optimization https://www.isaced.com/post-272.html
- Testing SQLite with 400 Million Order Rows Per Day https://cloud.tencent.com/developer/article/1016993
ViewModel
ViewModel is important in layered architecture. Besides ViewModel there's also a concept called DTO (Data Transfer Object). ViewModel and DTO both belong to the Model layer in MVC architecture. DTO can also be called Input Model, because it's generally the object for data coming in from outside (as the name suggests). Then the Model we usually talk about can also be called Entity—these objects map directly to tables in the database. Generally you don't present Model directly in a View or Api, but present ViewModel, because we might process the output data, like adding or removing fields. Using Model definitely won't work—data tables are fixed.
Similarly, when receiving data, it doesn't necessarily coincide with the data tables either, so you need DTO. There's actually no strict boundary with ViewModel—you could use DTO for presentation too. I just feel that from the name, ViewModel is meant for presentation. Habit, haha.
Actually traditional MVC and MVVM patterns are already a bit behind the times. I think web applications nowadays should be designed according to DDD (Domain-Driven Design). But DDD is a bit complex for beginners, lots of concepts, and I shouldn't randomly explain it. I'll quote a Zhihu answer:
Simply put, DDD is: a project has multiple Bounded Contexts, for example one is the frontend facing users, another is the backend facing internal company staff. Each Bounded Context is divided into multiple aggregates. Each aggregate contains a bunch of objects that need to guarantee transactional consistency, meaning from a global perspective, each aggregate is treated as a whole. A common example is Order (order) and OrderLine (the products in an order). Entities including Aggregate roots have unique identifiers. The difference is that an aggregate root has a unique identifier globally, while other entities inside the aggregate only have unique identifiers within the aggregate (maybe you have a primary key in the database, but here it means conceptually this unique identifier doesn't mean much globally, only within the aggregate does it mean much). Additionally, value objects are objects without identifiers; their meaning lies in their values. You can think of it as: comparing whether two entities are the same only requires checking if IDs are equal, while comparing value objects requires checking whether every property inside is the same.
Author: 鲍牙叔 Link: https://www.zhihu.com/question/25256772/answer/77940547 Source: Zhihu Copyright belongs to the author. For commercial reprint please contact the author for authorization; for non-commercial reprint please indicate the source.
Then, with so many objects being converted back and forth, and many fields being similar, reassigning them one by one looks dumb and is completely unnecessary. That's when AutoMapper should be used. Specific usage is not in the scope of this article (see the official docs listed below), but one thing: AutoMapper is configurable, you can exclude fields you don't want. In Profile I wrote it like this:
public class VideoProfile : Profile {
private readonly List<string> _unmapped = new List<string> {
"HostEnvironment", "Previews", "OverallRating"
};
public VideoProfile() {
CreateMap<Video, VideoViewModel>();
ShouldMapProperty = (property) => !_unmapped.Contains(property.Name);
}
}
Put the fields you don't want in a List, then configure ShouldMapProperty with a lambda and you're good.
References
- AutoMapper https://docs.automapper.org/en/latest/Getting-started.html
- RESTful+FreeSql+AutoMapper https://luoyunchong.github.io/vovo-docs/dotnetcore/examples/freesql-sample-blog-restful-use-automapper.html#adding-profiles
- FreeSql and AutoMapper Handling Many-to-Many Query Mapping https://blog.csdn.net/XinShun/article/details/104755959
Some Notes on the C# Language

I've used C# for a long time, but I've almost never specifically studied the syntax. This language, emmm, has a low floor and a very high ceiling. It's easy to get started, but much more complex than Java, with lots of syntactic sugar, so many people in the community have a sense of superiority, haha. But actually the domestic ecosystem is pretty poor—just some training schools hyping it. Overseas though you can feel it's a fairly popular technology. When you run into problems, you might not find anything with Chinese keywords, but switch to English and you can easily search up lots of high-quality answers. You can only say the domestic tech environment has been led astray by big companies like Alibaba—everyone went to do Java, and many other good technologies and languages get no attention. What a shame……
This project didn't use anything fancy either, just generics, extension methods, higher-order functions and the like, used them like crazy. Here's a small snippet of code to look at haha~
public static IList<TViewModel> ToViewModels<TModel, TViewModel>(
this ISelect<TModel> data,
IService<TModel, TViewModel> service,
int limit = 0
) where TModel : class
where TViewModel : class {
var limitData = limit == 0 ? data : data.Limit(limit);
return limitData
.ToList()
.Select(service.Get)
.ToList();
}
public static IEnumerable<TViewModel> ToSampleViewModels<TModel, TViewModel>(
this ISelect<TModel> data,
IService<TModel, TViewModel> service,
int limit = 0
) where TModel : class
where TViewModel : class {
return data.ToViewModels(service)
.Shuffle()
.Take(limit);
}
This code one-click converts FreeSQL database query results to ViewModels. The conversion goes through Service. The functionality is simple, but making it an extension method and then calling it is just so satisfying—cuts a ton of duplicated code, very comfortable~
Then I was a bit unused to C#'s higher-order functions at first, because I was used to writing python, dart, and js, all map, reduce, filter. But in C#'s LINQ they changed the names: map corresponds to select, filter corresponds to where, which is very SQL-style. At first I couldn't even find them……
In short, the C# language is worth studying properly. It helps improve work efficiency and programming thinking! Just read more books!

References
- Differences Between IEnumerable, ICollection, IList, and List in C#
- Introduction to C# Higher-Order Functions https://www.jianshu.com/p/8a8f3743969b
A Few Libraries
Also saw a few libraries that seem pretty good. I haven't used them yet. I've already applied AspNetCore at work, so I should have a chance to use these libraries later hhh
- Util application framework: https://github.com/dotnetcore/Util/blob/master/readme.md
- Masuit.Tools: https://github.com/ldqk/Masuit.Tools
Welcome to Discuss
I've compiled a series of technical articles and materials. Reply linux, flutter, c#, netcore, android, kotlin, java, python, etc. in the backend of the WeChat official account "Programming Lab" to get related technical articles and materials. Also, if you have any questions you can leave a message in the official account backend~
_EOF_
Casual Notes on Cross-Platform Framework AspNetCore Development Practice
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
Blazor全栈是个陷阱
Blazor全栈?别逗了,这玩意儿就是陷阱。生态弱得可怜,AI都不给力,文档还老变。真以为能脱离前端?醒醒吧,小demo可以,真业务?省省吧。
2025-09-17 · AspNetCore · 约 1 分钟
梦想家装平台开发记录,Asp-Net-Core上手实践
DreamingHome Dreaming Home 梦想家,家装平台 EF Core概念 Model: 数据模型,一个普通的C#类 DbContext: 与数据库沟通的桥梁,一个数据库对应一个DbContext 注册EF Core服务 services.AddEntityFrameworkSqlite() .AddDbContextMainContext(options = option
2022-08-17 · AspNetCore · 约 1 分钟
以为要报废的哈啰电动车,被我 9.9 元修好了
自己动手修个报警器,成本不到10块,收获一堆废铁工具和虚无缥缈的成就感?这年头谁还当自己是修理工啊。花一两百找修车店,省得自己折腾,可人家连个破盒子就卖50,真是绝了。
2025-12-06 · 2025 · 约 1 分钟
记一次AndroidStudio在Linux环境上的奇葩错误,Argument-for-@NotNull-parameter-'messag
错误信息 Argument for @NotNull parameter 'message' of com/android/tools/idea/gradle/project/sync/GradleSyncState.syncFailed must not be null java.lang.IllegalArgumentException: Argument for @NotNull param
2022-05-27 · Android开发 · 约 1 分钟
讨论
共 0 条加载评论中…
