Ledbim.Mongo
1.2.0
dotnet add package Ledbim.Mongo --version 1.2.0
NuGet\Install-Package Ledbim.Mongo -Version 1.2.0
<PackageReference Include="Ledbim.Mongo" Version="1.2.0" />
<PackageVersion Include="Ledbim.Mongo" Version="1.2.0" />
<PackageReference Include="Ledbim.Mongo" />
paket add Ledbim.Mongo --version 1.2.0
#r "nuget: Ledbim.Mongo, 1.2.0"
#:package Ledbim.Mongo@1.2.0
#addin nuget:?package=Ledbim.Mongo&version=1.2.0
#tool nuget:?package=Ledbim.Mongo&version=1.2.0
Ledbim.Mongo
<p align="center"> <img src="ledbim_mongo_logo.png" alt="Ledbim.Mongo" width="120" /> </p>
<p align="center"> <strong>MongoDB · Repository Pattern · Soft Delete · Audit Trail · Pagination</strong><br/> Ledbim ekosistemi için MongoDB repository altyapısı. </p>
Kapsam
Ledbim.Mongo paketi şu bileşenleri sağlar:
| Bileşen | Açıklama |
|---|---|
| MongoBaseEntity | 3 varyantlı base entity — audit alanları ve soft delete dahil |
| IMongoRepository<T> | MongoDB CRUD ve pagination arayüzü |
| MongoRepository<T> | Soft delete, audit trail, bulk operations implementasyonu |
| AddMongoRepository<T> | Collection adı yapılandırılabilen tek satır DI kaydı |
Kurulum
dotnet add package Ledbim.Mongo
Bağımlılıklar
MongoDB.Driver v3.6.0
Microsoft.Extensions.Configuration v10.0.0
Ledbim.Core (project reference)
Hızlı Başlangıç
1. appsettings.json
{
"MongoDb": {
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "MyApp"
}
}
2. Entity Tanımlama
// En yaygın kullanım — MongoDB ObjectId ile
public class Product : MongoBaseEntityWithObjectId
{
public string Name { get; set; } = default!;
public decimal Price { get; set; }
public string Category { get; set; } = default!;
}
3. Program.cs
// 1. MongoDB altyapısı
builder.Services.AddMongoDb(builder.Configuration);
// 2. ICurrentUserAccessor (audit için zorunlu)
builder.Services.AddScoped<ICurrentUserAccessor, CurrentUserAccessor>();
// 3. Repository kaydı
builder.Services.AddMongoRepository<Product>("products");
4. Handler'da Kullanım
public class GetProductQueryHandler(IMongoRepository<Product> repo)
: IRequestHandler<GetProductQuery, Result<ProductDto>>
{
public async Task<Result<ProductDto>> Handle(GetProductQuery request, CancellationToken ct)
{
var product = await repo.GetAsync(x => x.Name == request.Name, ct);
if (product is null)
return Result<ProductDto>.Fail(ResultType.NotFound, "Ürün bulunamadı.");
return Result<ProductDto>.Success(ResultType.Success, product.ToDto());
}
}
Entity Varyantları
Üç farklı base sınıf bulunur — kullanım senaryosuna göre seçilir.
MongoBaseEntity (Id'siz)
public abstract class MongoBaseEntity
Audit ve soft delete alanları içerir, Id içermez. Kendi Id stratejisini tanımlamak isteyen entity'ler için kullanılır.
| Alan | BSON Adı | Açıklama |
|---|---|---|
CreatedDate |
createdDate |
Oluşturma tarihi |
CreatedBy |
createdBy |
Oluşturan kullanıcı |
UpdatedDate |
updatedDate |
Son güncelleme tarihi |
UpdatedBy |
updatedBy |
Son güncelleyen kullanıcı |
IsDeleted |
isDeleted |
Soft delete bayrağı |
DeletedDate |
deletedDate |
Silinme tarihi |
DeletedBy |
deletedBy |
Silen kullanıcı |
Tüm alanların setter'ı
internal'dir — repository dışından doğrudan atama yapılamaz.
MongoBaseEntityWithObjectId
public abstract class MongoBaseEntityWithObjectId : MongoBaseEntity
Standart kullanım — MongoDB'nin native ObjectId tipiyle Id otomatik üretilir.
public class Order : MongoBaseEntityWithObjectId
{
public Guid CustomerId { get; set; }
public decimal Total { get; set; }
public string Status { get; set; } = default!;
}
AddAsync() çağrısında Id default ise ObjectId.GenerateNewId() otomatik atanır.
MongoBaseEntity<TKey>
public abstract class MongoBaseEntity<TKey> : MongoBaseEntity
where TKey : IEquatable<TKey>
ObjectId dışında farklı Id tipleri kullanmak gerektiğinde (örneğin string, Guid, int):
public class LogEntry : MongoBaseEntity<string>
{
// Id string tipinde — dışarıdan atanır
public string Level { get; set; } = default!;
public string Message { get; set; } = default!;
}
public class Counter : MongoBaseEntity<int>
{
// Id int tipinde
public string Key { get; set; } = default!;
public long Value { get; set; }
}
Hangi varyantı seçmeli?
| Senaryo | Varyant |
|---|---|
| Standart MongoDB dokümanı | MongoBaseEntityWithObjectId |
| String veya Guid Id gerekiyor | MongoBaseEntity<string> / MongoBaseEntity<Guid> |
| Id yönetimini tamamen kendin yapacaksın | MongoBaseEntity |
IMongoRepository<T>
public interface IMongoRepository<T> where T : MongoBaseEntity
{
// Ekleme
Task<T> AddAsync(T entity, CancellationToken ct = default);
Task<IReadOnlyList<T>> AddRangeAsync(IEnumerable<T> entities, CancellationToken ct = default);
// Güncelleme
Task<T> UpdateAsync(T entity, CancellationToken ct = default);
Task UpdateRangeAsync(IEnumerable<T> entities, CancellationToken ct = default);
Task<long> UpdateManyAsync(
Expression<Func<T, bool>> predicate,
UpdateDefinition<T> update,
CancellationToken ct = default);
// Silme
Task DeleteAsync(T entity, CancellationToken ct = default);
Task DeleteAsync(Expression<Func<T, bool>> predicate, CancellationToken ct = default);
Task DeleteRangeAsync(IEnumerable<T> entities, CancellationToken ct = default);
// Okuma
Task<T?> GetAsync(Expression<Func<T, bool>>? predicate = null, CancellationToken ct = default);
Task<IEnumerable<T>> GetAllAsync(
Expression<Func<T, bool>>? predicate = null,
Func<IQueryable<T>, IOrderedQueryable<T>>? orderBy = null,
CancellationToken ct = default);
Task<PagedModel<T>> GetAllPagedAsync(MongoPagedFilterRequest<T> filterRequest, CancellationToken ct = default);
Task<long> GetCountAsync(Expression<Func<T, bool>>? predicate = null, CancellationToken ct = default);
// Doğrudan collection erişimi
IMongoCollection<T> Collection { get; }
}
Kullanım Örnekleri
// Tekil kayıt
var product = await repo.GetAsync(x => x.Id == id, ct);
// Koşulla listeleme + sıralama
var products = await repo.GetAllAsync(
predicate: x => x.Category == "Electronics" && x.Price < 1000,
orderBy: q => q.OrderByDescending(x => x.Price),
ct);
// Sayım
var count = await repo.GetCountAsync(x => x.Status == "Active", ct);
// Kısmi güncelleme (UpdateDefinition ile)
var updated = await repo.UpdateManyAsync(
predicate: x => x.Status == "Draft",
update: Builders<Product>.Update.Set(x => x.Status, "Published"),
ct);
// Doğrudan collection — aggregation için
var pipeline = repo.Collection.Aggregate()
.Match(x => x.Category == "Electronics")
.Group(x => x.Category, g => new { Category = g.Key, Count = g.Count() });
Soft Delete
Varsayılan olarak tüm okuma sorguları IsDeleted == false filtresi uygular.
// Silinmemiş kayıtları getirir (varsayılan)
var products = await repo.GetAllAsync(x => x.Category == "Electronics");
// Silinmiş kayıtları da dahil et
var request = new MongoPagedFilterRequest<Product>
{
FilterQuery = new PaginationFilterQuery { PageNumber = 1, PageSize = 20 },
IgnoreQueryFilters = true // soft delete bypass
};
var all = await repo.GetAllPagedAsync(request, ct);
Fiziksel silme: Entity IHardDelete implement ederse DeleteAsync() dokümanı veritabanından tamamen kaldırır.
public class TempLog : MongoBaseEntityWithObjectId, IHardDelete
{
public string Message { get; set; } = default!;
}
// Fiziksel silme gerçekleşir
await repo.DeleteAsync(log, ct);
Audit Trail
AddAsync, UpdateAsync ve DeleteAsync çağrılarında audit alanları otomatik doldurulur. ICurrentUserAccessor DI'ya kayıtlı olmalıdır.
| İşlem | Doldurulan Alanlar |
|---|---|
AddAsync |
CreatedDate, CreatedBy, UpdatedDate, UpdatedBy |
UpdateAsync |
UpdatedDate, UpdatedBy |
DeleteAsync (soft) |
IsDeleted, DeletedDate, DeletedBy, UpdatedDate, UpdatedBy |
ICurrentUserAccessor implementasyonu:
public class CurrentUserAccessor(IHttpContextAccessor httpContextAccessor) : ICurrentUserAccessor
{
public string? GetCurrentUser()
{
return httpContextAccessor.HttpContext?.User
.FindFirstValue(ClaimTypes.NameIdentifier);
}
}
// Program.cs
builder.Services.AddScoped<ICurrentUserAccessor, CurrentUserAccessor>();
Pagination
var request = new MongoPagedFilterRequest<Product>
{
FilterQuery = new PaginationFilterQuery
{
PageNumber = 1,
PageSize = 20
},
Predicate = x => x.Category == "Electronics",
OrderBy = q => q.OrderByDescending(x => x.Price),
IgnoreQueryFilters = false
};
PagedModel<Product> result = await repo.GetAllPagedAsync(request, ct);
// result.TotalRecords — toplam kayıt sayısı
// result.PagedData — sayfa verisi
DI Kayıt Detayları
// AddMongoDb overload'ları
services.AddMongoDb(configuration); // IConfiguration'dan okur
services.AddMongoDb(settings); // MongoDbSettings nesnesi
services.AddMongoDb("mongodb://localhost", "MyDb"); // Direkt parametre
// Repository kaydı
services.AddMongoRepository<Product>(); // Collection adı = "Product"
services.AddMongoRepository<Product>("products"); // Collection adı = "products"
services.AddMongoRepository<Order>("orders");
Kayıt sırası önemlidir:
// 1. Önce MongoDB altyapısı
builder.Services.AddMongoDb(builder.Configuration);
// 2. ICurrentUserAccessor (audit için — AddMongoRepository'den önce)
builder.Services.AddScoped<ICurrentUserAccessor, CurrentUserAccessor>();
// 3. Repository'ler
builder.Services.AddMongoRepository<Product>("products");
builder.Services.AddMongoRepository<Order>("orders");
Tam Kullanım Örneği
// Entity
public class BlogPost : MongoBaseEntityWithObjectId
{
public string Title { get; set; } = default!;
public string Content { get; set; } = default!;
public string AuthorId { get; set; } = default!;
public string Status { get; set; } = "Draft";
public List<string> Tags { get; set; } = [];
}
// Command
public record PublishPostCommand(ObjectId PostId) : IRequest<Result>, ICommand;
// Handler
public class PublishPostCommandHandler(IMongoRepository<BlogPost> repo)
: IRequestHandler<PublishPostCommand, Result>
{
public async Task<Result> Handle(PublishPostCommand request, CancellationToken ct)
{
var post = await repo.GetAsync(x => x.Id == request.PostId, ct);
if (post is null)
return Result.Fail(ResultType.NotFound, "Yazı bulunamadı.");
if (post.Status == "Published")
return Result.Fail(ResultType.Conflict, "Yazı zaten yayında.");
post.Status = "Published";
await repo.UpdateAsync(post, ct);
return Result.Success(ResultType.Success, "Yazı yayınlandı.");
}
}
// Query — sayfalı listeleme
public class GetPostsQueryHandler(IMongoRepository<BlogPost> repo)
: IRequestHandler<GetPostsQuery, Result<PagedModel<BlogPostDto>>>
{
public async Task<Result<PagedModel<BlogPostDto>>> Handle(
GetPostsQuery request, CancellationToken ct)
{
var filterRequest = new MongoPagedFilterRequest<BlogPost>
{
FilterQuery = new PaginationFilterQuery
{
PageNumber = request.Page,
PageSize = request.PageSize
},
Predicate = x => x.Status == "Published",
OrderBy = q => q.OrderByDescending(x => x.CreatedDate)
};
var paged = await repo.GetAllPagedAsync(filterRequest, ct);
var dto = new PagedModel<BlogPostDto>
{
TotalRecords = paged.TotalRecords,
PagedData = paged.PagedData.Select(p => p.ToDto())
};
return Result<PagedModel<BlogPostDto>>.Success(ResultType.Success, dto);
}
}
Mimari Notlar
- ICurrentUserAccessor zorunludur:
AddMongoRepository<T>()kayıt sırasındaICurrentUserAccessorDI'da bulunmalıdır. Yoksa runtime'daInvalidOperationExceptionfırlatır. - Write metodlar SaveChanges çağırmaz: EF Core repository'sinden farklı olarak MongoDB repository'si her işlemi anında persist eder — ayrıca commit gerekmez.
- ObjectId otomatik üretimi:
MongoBaseEntityWithObjectIdkullanan entity'lerdeAddAsync()çağrısında Iddefaultise repository tarafından otomatik atanır. Collectionproperty'si: Aggregation pipeline, full-text search veya bulk write gibi sürücü seviyesinde operasyonlar için doğrudanIMongoCollection<T>'ye erişim sağlar.- LINQ → MongoDB query: Tüm
Expression<Func<T, bool>>ifadeleri MongoDB .NET Driver'ın LINQ provider'ı aracılığıyla MongoDB query'sine çevrilir.
Lisans
Bu paket Ledbim Bilişim tarafından geliştirilmektedir. Ticari kullanım için lisans bilgisi için iletişime geçiniz.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Ledbim.Core (>= 1.2.0)
- Microsoft.Extensions.Configuration (>= 10.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.0)
- MongoDB.Driver (>= 3.6.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.0 | 158 | 3/28/2026 |