2011-11-11 115 views
2

假設您有下一個課程。它包含在代理已工作使用C更新mongodb中的嵌入式文檔#

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

,你能否告訴代理類? –

+0

public class Agent { public string LocalIdentifier {get;組; } public string AgentName {get;組; } } –

回答

1

你不必如此冗長:BsonValue.Create()BsonArray.Create不應要求。

事實上,後者是您的問題的原因:BsonArray.Create創建值類型數組。但是,您需要一組對象。如果你看看BsonArray.Create的可用超載,我想你會調用BsonArray.Create(IEnumerable),這是不可取的。

您是否嘗試過簡單地使用

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

呢?

在JSON,所不同的是這樣的:

值數組:[纈氨酸,纈氨酸,...]

陣列對象的:[{...},{ ...},...]

例如,

簡單陣列:[ "mongodb", "awesomness", ... ]

對象數組:[ { userId: 2314234, comment: "Foo" }, { ... }, ... ]

+0

它仍然無法映射該類型,無論如何你添加的語法正是我想要的,謝謝 –

+0

我猜'_mongoCollection.Update(BuildIdentityQuery(實體),Update.AddToSetEachWrapped(「Agents」,entity.Agents) ,SafeMode.True);'應該工作,因爲Update.Set(也)不接受任何列表或文檔。但是,您無法「重置」列表,只能添加**或**刪除。或者,只需更新整個對象或將該列表包裝在自己的對象中,然後使用'Update.SetWrapped'。 – mnemosyn

+0

很酷,它的作品。你能解釋我爲什麼Update.Set不接受任何列表或文件? –