Perbarui dokumen Tertanam di mongodb menggunakan C#

Misalkan Anda memiliki kelas berikutnya. Ini berisi sistem di mana agen telah bekerja

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

Sekarang ketika saya mendapatkan agen baru saya melakukan hal berikutnya:

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

Dan metode selanjutnya di repositori:

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

Saya mendapatkan pengecualian berikutnya .NET type Riverdale.Domain.BO.Agent tidak dapat dipetakan ke BsonValue. Apa yang saya lakukan salah? Apa pendekatan yang tepat untuk memperbarui koleksi yang disematkan?

Berikut adalah aplikasi konsol sederhana yang muncul (seperti 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);
        }
    }

person Yurii Hohan    schedule 11.11.2011    source sumber
comment
Bisakah Anda menunjukkan kelas Agen?   -  person Christian Horsdal    schedule 11.11.2011
comment
Agen kelas publik { public string LocalIdentifier { dapatkan; mengatur; } string publik Nama Agen { dapatkan; mengatur; } }   -  person Yurii Hohan    schedule 11.11.2011


Jawaban (1)


Anda tidak harus terlalu bertele-tele: BsonValue.Create() dan BsonArray.Create tidak wajib diisi.

Faktanya, yang terakhir adalah penyebab masalah Anda: BsonArray.Create membuat array tipe nilai. Namun Anda memerlukan serangkaian objek. Jika Anda melihat kelebihan BsonArray.Create yang tersedia, saya kira Anda akan memanggil BsonArray.Create(IEnumerable), yang tidak diinginkan.

Sudahkah Anda mencoba menggunakan saja

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

alih-alih?

Di JSON, perbedaannya terlihat seperti ini:

Array Nilai: [ val, val, ... ]

Array Objek: [ { ... }, { ... }, ... ]

Misalnya,

Susunan Sederhana: [ "mongodb", "awesomness", ... ]

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

person mnemosyn    schedule 11.11.2011
comment
Masih tidak dapat memetakan tipe itu, bagaimanapun sintaks yang Anda tambahkan persis seperti yang saya inginkan, terima kasih - person Yurii Hohan; 11.11.2011
comment
Saya kira _mongoCollection.Update(BuildIdentityQuery(entity), Update.AddToSetEachWrapped("Agents", entity.Agents), SafeMode.True); seharusnya berfungsi, karena Update.Set (juga) tidak menerima daftar atau dokumen apa pun. Namun, Anda tidak dapat 'mengatur ulang' daftar tersebut, Anda hanya dapat menambahkan atau menghapus. Alternatifnya, cukup perbarui seluruh objek atau gabungkan daftar dalam objeknya sendiri, dan gunakan Update.SetWrapped. - person mnemosyn; 11.11.2011
comment
Keren, itu berhasil. Bisakah Anda menjelaskan mengapa Update.Set tidak menerima daftar atau dokumen apa pun? - person Yurii Hohan; 11.11.2011
comment
Saya tidak tahu mengapa dirancang seperti ini; Saya berasumsi bahwa membuat serial objek kompleks lebih rumit (yaitu lebih lambat). Cara penerapannya sekarang, bisa menjamin kinerja yang baik. Pemanggilan serializer khusus, dll. mungkin juga berperan. - person mnemosyn; 11.11.2011
comment
Terkadang saya mendapatkan hasil yang aneh seperti screencast.com/t/plkzxj2b7Sb7 . Tidak dapat memahami mekanisme di balik kerjanya - person Yurii Hohan; 11.11.2011
comment
Kasus ditutup, Punya daftar, bukan array - person Yurii Hohan; 11.11.2011