使用C#在MongoDB中更新嵌入文档 [英] Update Embedded document in mongodb using C#

查看:144
本文介绍了使用C#在MongoDB中更新嵌入文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你有隔壁班的。它包含在该代理已制定

 公共类AgentHistory 
{
公众的ObjectId标识{系统得到;组; }
公众的Guid SYSTEMID {搞定;组; }
公众的Guid CAMPAIGNID {搞定;组; }
公开名单<剂>代理{搞定;组; }
}

现在,当我得到我做的下一件事一个新的代理:

 公众覆盖AgentHistory保存(AgentHistory剂)
{
如果(代理== NULL)
抛出新的ArgumentNullException(代理);
如果(_repository.Exists(剂))
{
AgentHistory dbEntity = _repository.FindById(agent.SystemId,agent.CampaignId);
dbEntity.Agents.AddRange(agent.Agents);
_repository.UpdateAgentHistory(dbEntity);
}
,否则
{
_repository.Save(剂);
}
返回剂;
}

和在库中的下一个方法:

 公共无效UpdateAgentHistory(AgentHistory updatedEntity)
{
QueryComplete查询= Query.EQ(_ ID,BsonValue.Create(updatedEntity.Id) );

MongoCollection.Update(查询,Update.Set(代理人,BsonArray.Create(updatedEntity.Agents)),UpdateFlags.None,SafeMode.True);
}



我得到了一个异常 .NET类型Riverdale.Domain.BO .Agent不能被映射到BsonValue。我在做什么错了? ?什么是更新嵌入式集合的正确方法



下面是一个简单的控制台应用程序,它抛出(就像演示):

 公共类代理
{
[BsonId]
公共字符串LocalIdentifier {搞定;组; }

公共字符串AGENTNAME {搞定;组; }
}

公共A级
{
公众的ObjectId标识{搞定;组; }
公众的Guid SYSTEMID {搞定;组; }
公众的Guid CAMPAIGNID {搞定;组; }
公共代理[] {代理商获取;组; }
}

公共类AgentHistoryRepository
{
公共BOOL存在(A agentHistory)
{
返回_mongoCollection.FindOne(BuildIdentityQuery(agentHistory ))!= NULL;
}

公共无效删除(A agentHistory)
{
_mongoCollection.Remove(BuildIdentityQuery(agentHistory));
}

公开名单<串GT; GetAgentsForASystem(GUID systemGuid)
{
QueryComplete查询= Query.EQ(SYSTEMID,systemGuid);
返回_mongoCollection.Find(查询).SelectMany(X => x.Agents.Select(Z => z.AgentName))。鲜明()了ToList();
}

公开名单<串GT; GetAgentsForACampaign(GUID systemGuid中GUID campaignGuid)
{
QueryComplete查询= Query.EQ(CAMPAIGNID,campaignGuid);
如果(systemGuid = Guid.Empty!)
=查询Query.And(新[] {查询,Query.EQ(SYSTEMID,systemGuid)});
返回_mongoCollection.Find(查询).SelectMany(X => x.Agents.Select(Z => z.AgentName))。鲜明()了ToList();
}

公共AgentHistoryRepository()
{
字符串的connectionString =的MongoDB://本地主机/样本;
变种mgsb =新MongoUrlBuilder(的connectionString);
变种MongoServer = MongoDB.Driver.MongoServer.Create(mgsb.ToMongoUrl());
VAR MongoDatabase = MongoServer.GetDatabase(mgsb.DatabaseName);
_mongoCollection = MongoDatabase.GetCollection< A>(AgentHistory);
}


私人MongoCollection< A> _mongoCollection;

私人QueryComplete BuildIdentityQuery(A agentHistory)
{
QueryComplete查询= Query.And(Query.EQ(SYSTEMID,agentHistory.SystemId),
查询。 EQ(CAMPAIGNID,agentHistory.CampaignId));
返回查询;
}

公共无效保存(实体)
{
_mongoCollection.Insert(实体,SafeMode.True);
}

公共无效UpdateAgents(A实体)
{
_mongoCollection.Update(BuildIdentityQuery(实体),Update.Set(代理人,entity.Agents。 ToBs​​onDocument()));
}
}

内部类节目
{
公共静态无效的主要()
{

变种objectToSave =新的A {ID = ObjectId.GenerateNewId(),CAMPAIGNID = Guid.NewGuid(),SYSTEMID = Guid.NewGuid(),
=代理新的[] {新代理{LocalIdentifier =代理人,AGENTNAME = 名称}}};

变种回购=新AgentHistoryRepository();
repo.UpdateAgents(objectToSave);
objectToSave.Agents =新[] {新代理{LocalIdentifier =agent2,AGENTNAME =NAME2}};
repo.UpdateAgents(objectToSave);
变种objectToSave2 =新的A
{
n = ObjectId.GenerateNewId(),
CAMPAIGNID = Guid.NewGuid(),
SYSTEMID = objectToSave.SystemId,
=代理新的[] {新代理{LocalIdentifier =代理人,AGENTNAME =名字}}
};
repo.UpdateAgents(objectToSave2);
的foreach(在repo.GetAgentsForASystem(objectToSave.SystemId VAR AGENTNAME))
Console.WriteLine(AGENTNAME);
}
}


解决方案

您不必那么详细。 BsonValue.Create() BsonArray.Create 不应该要求



在事实上,后者是你的问题的原因: BsonArray.Create 创造价值类型的阵列。你需要对象的数组,但是。如果你看看 BsonArray.Create 的可用过载,我猜你会调用 BsonArray.Create(IEnumerable的),这是不可取的。



您是否尝试过简单的使用

  MongoCollection.Update(查询,Update.Set(代理人,updatedEntity.Agents),...); 



呢?



在JSON中,区别是这样的:




值的

数组:VAL,VAL,...]

对象

阵:[{...},{...},...]



< /块引用>

例如,



简单阵列: [MongoDB的,awesomne​​ss ...]



对象的数组: [{用户名:2314234,评论:富},{ ...},...]


Suppose you have the next class. It contains the systems in which the agent has worked

public class AgentHistory
{
    public ObjectId Id { get; set; }
    public Guid SystemId { get; set; }
    public Guid CampaignId { get; set; }
    public List<Agent> Agents { get; set; }
}

Now when I get a new agent I do the next thing:

 public override AgentHistory Save(AgentHistory agent)
    {
        if (agent == null)
            throw new ArgumentNullException("agent");
        if (_repository.Exists(agent))
        {
            AgentHistory dbEntity = _repository.FindById(agent.SystemId, agent.CampaignId);
            dbEntity.Agents.AddRange(agent.Agents);
            _repository.UpdateAgentHistory(dbEntity);
        }
        else
        {
            _repository.Save(agent);
        }
        return agent;
    }

And the next method in repository:

public void UpdateAgentHistory(AgentHistory updatedEntity)
    {
        QueryComplete query = Query.EQ("_id", BsonValue.Create(updatedEntity.Id));

        MongoCollection.Update(query, Update.Set("Agents", BsonArray.Create(updatedEntity.Agents)), UpdateFlags.None, SafeMode.True );
    }

I get the next exception .NET type Riverdale.Domain.BO.Agent cannot be mapped to a BsonValue. What am I doing wrong? What is the right approach to updating embedded collections?

Here is a simpler console app which throws(just as a demo):

  public class Agent
    {
        [BsonId]
        public string LocalIdentifier { get; set; }

        public string AgentName { get; set; }
    }

    public class A
    {
        public ObjectId Id { get; set; }
        public Guid SystemId { get; set; }
        public Guid CampaignId { get; set; }
        public Agent[] Agents { get; set; }
    }

    public class AgentHistoryRepository
    {
        public bool Exists(A agentHistory)
        {
            return _mongoCollection.FindOne(BuildIdentityQuery(agentHistory)) != null;
        }

        public void Delete(A agentHistory)
        {
            _mongoCollection.Remove(BuildIdentityQuery(agentHistory));
        }

        public List<string> GetAgentsForASystem(Guid systemGuid)
        {
            QueryComplete query = Query.EQ("SystemId", systemGuid);
            return _mongoCollection.Find(query).SelectMany(x => x.Agents.Select(z => z.AgentName)).Distinct().ToList();
        }

        public List<string> GetAgentsForACampaign(Guid systemGuid, Guid campaignGuid)
        {
            QueryComplete query = Query.EQ("CampaignId", campaignGuid);
            if (systemGuid != Guid.Empty)
                query = Query.And(new[] {query, Query.EQ("SystemId", systemGuid)});
            return _mongoCollection.Find(query).SelectMany(x => x.Agents.Select(z => z.AgentName)).Distinct().ToList();
        }

        public AgentHistoryRepository()
        {
            string connectionString = "mongodb://localhost/Sample";
            var mgsb = new MongoUrlBuilder(connectionString);
            var MongoServer = MongoDB.Driver.MongoServer.Create(mgsb.ToMongoUrl());
            var MongoDatabase = MongoServer.GetDatabase(mgsb.DatabaseName);
            _mongoCollection = MongoDatabase.GetCollection<A>("AgentHistory");
        }


        private MongoCollection<A> _mongoCollection;

        private QueryComplete BuildIdentityQuery(A agentHistory)
        {
            QueryComplete query = Query.And(Query.EQ("SystemId", agentHistory.SystemId),
                                            Query.EQ("CampaignId", agentHistory.CampaignId));
            return query;
        }

    public void Save(A entity)
        {
            _mongoCollection.Insert(entity, SafeMode.True);
        }

        public void UpdateAgents(A entity)
        {
            _mongoCollection.Update(BuildIdentityQuery(entity), Update.Set("Agents", entity.Agents.ToBsonDocument()));
        }
    }

    internal class Program
    {
        public static void Main()
        {

            var objectToSave =  new A {Id = ObjectId.GenerateNewId(), CampaignId=Guid.NewGuid(), SystemId =Guid.NewGuid() ,
                                     Agents = new [] {new Agent{LocalIdentifier="agent", AgentName= "name"}}};

            var repo = new AgentHistoryRepository();
            repo.UpdateAgents(objectToSave);
            objectToSave.Agents = new[] { new Agent { LocalIdentifier = "agent2", AgentName = "name2" } };
            repo.UpdateAgents(objectToSave);
            var objectToSave2 = new A
            {
                Id = ObjectId.GenerateNewId(),
                CampaignId = Guid.NewGuid(),
                SystemId = objectToSave.SystemId,
                Agents = new [] { new Agent { LocalIdentifier = "agent", AgentName = "name" } }
            };
            repo.UpdateAgents(objectToSave2);
            foreach (var agentName in repo.GetAgentsForASystem(objectToSave.SystemId))
                Console.WriteLine(agentName);
        }
    }

解决方案

You don't have to be so verbose: BsonValue.Create() and BsonArray.Create should not be required.

In fact, the latter is the cause of your problem: BsonArray.Create creates arrays of value types. You need an array of objects, however. If you take a look at the available overloads of BsonArray.Create, I guess you'll be invoking BsonArray.Create(IEnumerable), which is not desirable.

Have you tried to simply use

MongoCollection.Update(query, Update.Set("Agents", updatedEntity.Agents), ...);

instead?

In JSON, the difference looks like this:

Array of Values: [ val, val, ... ]

Array of Objects: [ { ... }, { ... }, ... ]

For example,

Simple Array: [ "mongodb", "awesomness", ... ]

Array of Objects: [ { userId: 2314234, comment: "Foo" }, { ... }, ... ]

这篇关于使用C#在MongoDB中更新嵌入文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆