อัปเดตเอกสารฝังตัวใน mongodb โดยใช้ C #

สมมติว่าคุณมีชั้นเรียนถัดไป ประกอบด้วยระบบที่ตัวแทนทำงาน

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

ตอนนี้เมื่อฉันได้ตัวแทนใหม่ ฉันจะทำสิ่งต่อไป:

 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;
    }

และวิธีการถัดไปในพื้นที่เก็บข้อมูล:

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 );
    }

ฉันได้รับข้อยกเว้นถัดไป .NET ประเภท Riverdale.Domain.BO.Agent ไม่สามารถแมปกับ BsonValue ได้ ฉันทำอะไรผิด แนวทางที่ถูกต้องในการอัปเดตคอลเลกชันที่ฝังตัวคืออะไร?

นี่คือแอปคอนโซลที่ง่ายกว่าซึ่งพ่น (เช่นเดียวกับการสาธิต):

  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);
        }
    }

person Yurii Hohan    schedule 11.11.2011    source แหล่งที่มา
comment
คุณสามารถแสดงคลาส Agent ได้หรือไม่?   -  person Christian Horsdal    schedule 11.11.2011
comment
ตัวแทนคลาสสาธารณะ { สตริงสาธารณะ LocalIdentifier { รับ; ชุด; } AgentName สตริงสาธารณะ { รับ; ชุด; } }   -  person Yurii Hohan    schedule 11.11.2011


คำตอบ (1)


คุณไม่จำเป็นต้องละเอียดมากนัก: BsonValue.Create() และ BsonArray.Create ไม่ควรเป็นสิ่งที่จำเป็น

อันที่จริง อย่างหลังคือสาเหตุของปัญหาของคุณ: BsonArray.Create สร้างอาร์เรย์ของประเภทค่า อย่างไรก็ตาม คุณต้องมีอาร์เรย์ของวัตถุ หากคุณดูโอเวอร์โหลดที่มีอยู่ของ BsonArray.Create ฉันเดาว่าคุณจะเรียกใช้ BsonArray.Create(IEnumerable) ซึ่งไม่เป็นที่พึงปรารถนา

คุณลองใช้แล้วหรือยัง

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

แทน?

ใน JSON ความแตกต่างจะเป็นดังนี้:

อาร์เรย์ของค่า: [ val, val, ... ]

อาร์เรย์ของออบเจ็กต์: [ { ... }, { ... }, ... ]

ตัวอย่างเช่น,

อาร์เรย์แบบง่าย: [ "mongodb", "awesomness", ... ]

อาร์เรย์ของวัตถุ: [ { userId: 2314234, comment: "Foo" }, { ... }, ... ]

person mnemosyn    schedule 11.11.2011
comment
มันยังไม่สามารถแมปประเภทนั้นได้ แต่ไวยากรณ์ที่คุณเพิ่มนั้นตรงกับที่ฉันต้องการ ขอบคุณ - person Yurii Hohan; 11.11.2011
comment
ฉันเดาว่า _mongoCollection.Update(BuildIdentityQuery(entity), Update.AddToSetEachWrapped("Agents", entity.Agents), SafeMode.True); น่าจะใช้ได้ เพราะ Update.Set (เช่นกัน) ไม่ยอมรับรายการหรือเอกสารใดๆ อย่างไรก็ตาม คุณไม่สามารถ 'รีเซ็ต' รายการได้ คุณสามารถเพิ่มได้เพียง หรือ ลบเท่านั้น อีกวิธีหนึ่ง เพียงอัปเดตออบเจ็กต์ทั้งหมดหรือรวมรายการไว้ในออบเจ็กต์ของตนเอง และใช้ Update.SetWrapped - person mnemosyn; 11.11.2011
comment
เจ๋ง มันได้ผล คุณช่วยอธิบายฉันหน่อยได้ไหมว่าทำไม Update.Set จึงไม่ยอมรับรายการหรือเอกสารใด ๆ - person Yurii Hohan; 11.11.2011
comment
ฉันไม่รู้ว่าทำไมมันถึงออกแบบแบบนี้ ฉันคิดว่าการทำให้วัตถุที่ซับซ้อนเป็นอนุกรมนั้นซับซ้อนกว่า (เช่นช้าลง) วิธีดำเนินการตอนนี้สามารถรับประกันประสิทธิภาพที่ดีได้ การเรียกใช้ซีเรียลไลเซอร์แบบกำหนดเอง ฯลฯ อาจมีบทบาทเช่นกัน - person mnemosyn; 11.11.2011
comment
บางครั้งฉันได้รับผลลัพธ์แปลกๆ เช่น screencast.com/t/plkzxj2b7Sb7 ไม่สามารถเข้าใจกลไกเบื้องหลังการทำงานได้จริงๆ - person Yurii Hohan; 11.11.2011
comment
ปิดเคสแล้ว มีรายการแทนอาร์เรย์ - person Yurii Hohan; 11.11.2011