C# MongoDB:如何映射领域对象(需要在Id属性上使用BsonIgnoreIfDefault)

3

我已经开始了一个小而简单的项目(一个非常原始的博客),以获取一些关于DDD的实践经验。虽然我相信我理解了基本概念,但我还没有能够解决以下问题。

给定一个POCO对象'post',我想使用一个存储库将其持久化,该存储库使用mongodb集合更新方法和upsert参数进行实现(请参见下面的代码)。

public Post Save(Post p)
{
    var wc = collection.Update(
    Query<Post>.EQ<string>(p0 => p0.permalink, p.permalink),
    Update<Post>.Replace(p),
    UpdateFlags.Upsert);
    return p;
}

然而,为了使upsert正常工作,似乎需要将mongodb特定属性应用于您的Id字段,详见此答案: https://dev59.com/KGIj5IYBdhLWcg3weFCq#20224022 因此,我只能看到两种可能的行动方案:
1)在我的域库项目中添加对mongodb程序集的引用,但感觉不太合适,因为mongodb是存储库实现细节(因此属于DAL)。
2)将“post”实例(poco域对象)传递给PostRepository实现,并通过将域对象映射到和从DTO进行处理来处理任何与实现相关的问题。
虽然第二个解决方案似乎符合DDD原则,但其实施成本也比第一个更高,因此我想知道是否存在更好的替代方案。
提前感谢您的反馈。
1个回答

2

您不必使用属性来映射 Id,在 DAL 中可以使用 RegisterClassMap 来实现:

BsonClassMap.RegisterClassMap<Post>(cm =>
{
    cm.AutoMap();
    cm.SetIdMember(cm.GetMemberMap(p => p.Id));
});

顺便说一下:您可以执行upsert操作,而无需映射Id,但是您不能使用简单的Update<Post>.Replace(p)。您需要自己创建一个更新。


你能详细说明一下“你需要自己创建更新”是什么意思吗?我不确定我理解你的意思,谢谢! - Andrea Scarcella
1
当您使用 Update<Post>.Replace(p) 时,它会创建一个更新查询,根据 _id 字段替换所有字段的新数据。这是一种经典的 upsert 操作,您可以用具有相同 ID 的新对象覆盖所有字段。然而,有时您可能需要一种不仅仅是简单地覆盖一切的不同方法。当您提供自己构建的特定查询时,您可以实现这样的操作。不过,第一种选项更好。 - i3arnon
我通过添加以下内容扩展了您的答案:BsonClassMap.RegisterClassMap<Post>(cm => { cm.AutoMap(); cm.SetIdMember(cm.GetMemberMap(p => p.Id).SetIgnoreIfDefault(true)); });这使我能够插入两个文档,但是我无法读取它们,因为我会收到“无法从BsonType ObjectId反序列化Guid”异常。 - Andrea Scarcella
@AndreaScarcella,您不想插入具有相同ID的2个项目。您只需要指定哪个字段保存ID即可获得一个项目。当然,ID本身必须是新的唯一ID(这意味着是新文档),或者是现有的ID(这意味着是现有项目)。 - i3arnon
1
总结:感谢I3arnon的帮助,出现了一个新的需求,将在新问题中解决。被接受的答案中提供的解决方案在upsert时不会生成新的id。 - Andrea Scarcella
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接