Why C# is Not Just a Language, But a Whole Universe of Tools
\nWhen a developer first starts diving into the .NET world, they often think: "C# is cool, but what can I do right now?" The answer is simple: use libraries. The C# ecosystem is so rich that sometimes it seems like there is already a ready-made solution on NuGet for any task. And that's great, because popular C# libraries allow you not to reinvent the wheel, but to focus on business logic.
\nIn this article, we will break down the .NET library ecosystem that every developer really needs. We won't just list names — I'll show code examples, explain where to use what, and give practical tips. Let's go!
\n\nLogging: Serilog vs NLog — Battle of the Titans
\nLogging is the first thing you should think about. Without logs, you are blind. The Serilog library has become the de facto standard in the .NET world. Why? Because it can send logs anywhere: to a file, console, Elasticsearch, database. And all with minimal setup.
\nExample: Setting up Serilog in ASP.NET Core
\nusing Serilog;\n\nLog.Logger = new LoggerConfiguration()\n .WriteTo.Console()\n .WriteTo.File("logs/myapp-.txt", rollingInterval: RollingInterval.Day)\n .CreateLogger();\n\nvar builder = WebApplication.CreateBuilder(args);\nbuilder.Host.UseSerilog();\n\nvar app = builder.Build();\napp.MapGet("/", () => "Hello World!");\napp.Run();\nNLog is also a powerful tool, but it requires more configuration in XML. If you want simple and fast — choose Serilog. If you need full control — choose NLog. But for 90% of projects, Serilog will be the optimal choice.
\n\nEntity Framework Core: An ORM You Shouldn't Fear
\nWorking with databases is a pain for every developer. C# libraries for working with databases are divided into two camps: heavy ORMs (Entity Framework) and lightweight ones (Dapper). Entity Framework Core (EF Core) is a powerful tool that generates SQL for you. It is ideal for complex domain models.
\nExample: Simple CRUD with EF Core
\npublic class User\n{\n public int Id { get; set; }\n public string Name { get; set; }\n}\n\npublic class AppDbContext : DbContext\n{\n public DbSet<User> Users { get; set; }\n}\n\n// Usage\nusing var db = new AppDbContext();\nvar user = new User { Name = "Alexey" };\ndb.Users.Add(user);\ndb.SaveChanges();\nBut there is a nuance: EF Core can be slow on complex queries. For high-load systems, it is better to use Dapper — a micro-ORM that works many times faster but requires writing SQL manually.
\nWhen to choose Dapper?
\n- \n
- Maximum performance is needed \n
- You have simple queries (CRUD without complex logic) \n
- You are not afraid of SQL \n
using var connection = new SqlConnection(connectionString);\nvar users = connection.Query<User>("SELECT * FROM Users WHERE IsActive = @Active", new { Active = true });\n\nAutoMapper: Painless Mapping
\nIf you write in C#, you constantly encounter converting one object to another. DTO → Entity, Entity → ViewModel. Manual mapping is boring and error-prone. AutoMapper automates this process.
\nExample: Setting up a Profile
\npublic class UserProfile : Profile\n{\n public UserProfile()\n {\n CreateMap<User, UserDto>()\n .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"));\n }\n}\n\n// Usage\nvar config = new MapperConfiguration(cfg => cfg.AddProfile<UserProfile>());\nvar mapper = config.CreateMapper();\nvar dto = mapper.Map<UserDto>(user);\nTip: don't overuse AutoMapper. If the mapping is too