gpt4 book ai didi

C# Mongodb 驱动程序 : Translate Action into an UpdateDefinition

转载 作者:可可西里 更新时间:2023-11-01 10:19:56 24 4
gpt4 key购买 nike

我正在尝试将更新推广到我的 mongodb,这样我就可以更新我的数据 - 存储不可知。使用 EntityFramework,这非常容易,因为它具有更改跟踪功能,因此我可以将业务逻辑和特定于数据库的操作分开。至于 MongoDb,就没那么容易了,因为我必须创建这些 UpdateDefinitions,才能对文档进行更新。

模仿此操作的一种简单方法是使用 ReplaceOneAsync,但这不是一种选择,因为不止一方可能同时写入我的集合。例如,我在我的应用程序中将它用于聊天系统。

我想做这样的事情:

public class MongoActionWrapper<TCollection>
{
public MongoActionWrapper(Action<TCollection> updateAction)
{
UpdateAction = updateAction;
}

public Action<TCollection> UpdateAction { get; }
}

然后我有我的 MongoRepository:

public abstract class BaseMongoRepository<TAggregate, TCollection> : IRepository<TAggregate> where TAggregate : BaseAggregateRoot, IMongoAggregate<TCollection>
{
private readonly IMongoCollection<TCollection> _mongoCollection;

protected BaseMongoRepository(IMongoCollection<TCollection> mongoCollection)
{
_mongoCollection = mongoCollection;
}

public async void SaveAsync(TAggregate aggregate)
{
var state = aggregate.GetState();
foreach (var action in state.ActionsToExecuteOnCollection)
{
await _mongoCollection.UpdateOneAsync<TCollection>(aggregate.GetSelector(), action.UpdateAction);
}
}
}

我想在集合而不是 UpdateDefinition 上执行操作的位置。或者以某种方式将我的 Action 转换为 UpdateDefinition。

这将使我能够在列表(或我想存储数据的任何其他集合)上应用相同的更新,这样我就不会被迫留在 mongodb 上。

到目前为止,我唯一的解决方案是让我的 UpdateAction 更像一个描述更新的对象,然后在我想将其保存在 mongodb 中时转换这些对象。这样我就可以将它们转换为 Actions 并将它们应用到我的收藏或我选择的任何其他数据库。

我希望有人有想法,因为我在这里没有其他选择。

最佳答案

我不确定你是如何使用 Action delegate 来做到这一点的,但是如果你想在单个 AggregateRoot 上重现 EntityFramework,比如 Read-Through、Write-Through 缓存和多个并发写入,你可以尝试这样的事情:

public abstract class AggregateRoot<T> where T : AggregateRoot<T>
{
internal UpdateDefinition<T> UpdateDefinition { get; internal set; }
internal void Aggregate(UpdateDefinition<T> component)
{
if (component == null)
{
throw new ArgumentNullException("component");
}

if (this.UpdateDefinition == null)
{
this.UpdateDefinition = component;
}
else
{
this.UpdateDefinition = Builders<T>.Update.Combine
(this.UpdateDefinition, component);
}
}
}

并且比存储库基类中的:

public class Repository<T> where T : AggregateRoot<T>
{
private ConcurrentDictionary<ObjectId, T> cache
= new ConcurrentDictionary<ObjectId, T>();

private IMongoCollection<T> collection;

public Repository(string connectionString, string databaseName, string collectionName)
{
collection = new MongoClient(connectionString)
.GetDatabase(databaseName)
.GetCollection<T>(collectionName);
}

public T Find(ObjectId aggregateRootId)
{
return cache.GetOrAdd(
key: aggregateRootId,
valueFactory: key => findById(key));
}

private T findById(ObjectId aggregateRootId)
{
return collection
.Find(Builders<T>.Filter
.Eq(x => x.Id, aggregateRootId))
.SingleOrDefault();
}

public void SaveChanges()
{
var writeModels = generateWriteModels();
collection.BulkWrite(writeModels);
}

private IEnumerable<WriteModel<T>> generateWriteModels()
{
List<WriteModel<T>> writeModels = new List<WriteModel<T>>();

foreach (var cached in cache)
{
if (cached.Value != null)
{
if (cached.Value.UpdateDefinition != null)
{
writeModels.Add(new UpdateOneModel<T>(
filter: Builders<T>.Filter.Eq(x => x.Id, cached.Value.Id),
update: cached.Value.UpdateDefinition){ IsUpsert = true });
cached.Value.UpdateDefinition = null;
}
}
}

return writeModels;
}
}

通过此实现,您可以与 Aggregate(UpdateDefinition<T> component) 进行交互AggregateRoot<T>的方法|直接在实现中使用基类(注意不要在 setter 上使用它——BsonSerializer 也使用 setter)。 Repository<T> 将消耗更改.

如果你想让你的领域模型尽可能地与商店实现分离,你可以构建一个等价于 MongoActionWrapper<TCollection> 的模型。作为聚合的包装器。这些包装器可以将聚合方法与 Aggregate(UpdateDefinition<T> component) 一起使用使更新定义与对聚合所做的更改保持同步。

关于C# Mongodb 驱动程序 : Translate Action into an UpdateDefinition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40343759/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com