使用C#在MongoDB中更新嵌入文档 [英] Update Embedded document in mongodb using C#
问题描述
假设你有隔壁班的。它包含在该代理已制定
公共类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。 ToBsonDocument()));
}
}
内部类节目
{
公共静态无效的主要()
{
变种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的,awesomness ...]
对象的数组:
[{用户名: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()
andBsonArray.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 ofBsonArray.Create
, I guess you'll be invokingBsonArray.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屋!