C# 在Mongodb.net驱动程序中插入时验证文档

C# 在Mongodb.net驱动程序中插入时验证文档,c#,mongodb,validation,C#,Mongodb,Validation,假设我有个人数据模型: public class Person { public string Name { get; set; } public string Title { get; set; } } 如果在过去5分钟内插入了另一个具有相同名称和标题的文档,我想防止插入Person类型的新文档 所以我添加了CreatedAt和ValidTill public class Person { public string Name { get; set; }

假设我有个人数据模型:

public class Person
{
    public string Name { get; set; }
    public string Title { get; set; }
}
如果在过去5分钟内插入了另一个具有相同名称和标题的文档,我想防止插入Person类型的新文档

所以我添加了CreatedAt和ValidTill

  public class Person
 {
    public string Name { get; set; }
    public string Title { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime ValidTill { get; set; }
 }
我搜索了一种机制,如果我试图插入一个副本(我不想更新以前的文档),它将返回一个异常

我认为对我有用的是:

context.People.InsertOne(person, new InsertOneOptions() {
BypassDocumentValidation = !context.People.AsQueryable().Select(x => x.Title == person.Title && 
x.Name == person.Name && x.ValidTill > person.CreatedAt).Any()});
但是,当我使用它时,尽管BypassDocumentValidation的值为false,仍会插入重复的文档,我知道我需要使用:

DocumentValidationAction action = DocumentValidationAction.Error;

但是我不知道如何将它传递给insert。

您不能使用文档验证来完成此操作,但是您可以构造一个更新来完成您想要做的事情

mongo
shell语法中,可以执行以下操作:

now=new Date();
nowMinus5=new Date(now-5*60*1000);
db.collection.update(
    {name:"Asya", title:"Smartie", createdAt:{$gt:nowMinus5}},
    {
        $set:{name:"Asya"},
        $setOnInsert:{createdAt:now}  /* this is where you would put other fields to insert */
    },
    { upsert:true }
)
如果在5分钟内找到与
createdAt
相同的
name
title
,则会对其执行“no op”
update
name
被设置为已存在的名称)。如果未找到,则执行
insert
(通过
upsert
)操作,该操作可以将所有要设置的字段设置为
insert


您的应用程序可以通过检查更新返回的writeResult并将适当的消息返回给客户机/用户来确定发生了什么情况。

如果15或50分钟前插入了具有相同姓名和头衔的同一类型人员,该怎么办?那么可以吗?@AsyaKamsky是的,在我的情况下可以。您必须首先在集合上定义验证器(使用适当的操作)——插入操作中没有这样做,这是一个集合修改命令)。但验证也不是实现这一点的方法,因为当两次插入非常接近同一时间时,您很容易出现竞争条件-检查时不会出现重复,但在两次插入时都会出现重复。请注意,如果有多个线程创建文档,两个线程可以同时插入两个具有相同名称/标题的文档。您可以通过在名称、标题、createdAt时间上设置唯一索引来降低这种可能性,但是您应该将createdAt设置为比毫秒(可能是分钟)更高的粒度,尽管在分钟边界上仍然可能存在竞争条件)