我的mongo域对象中有继承:
public abstract class Entity : IEntity
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[BsonIgnore]
public abstract string CollectionName { get; }
}
[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(Sub1), typeof(Sub2), typeof(Sub3))]
public class Main:Entity
{
public string Name {get; set;}
public string Address {get; set;}
}
[BsonDiscriminator(SubType.Sub1)]
public class Sub1: Main, IWorkAttached
{}
[BsonDiscriminator(SubType.Sub2)]
public class Sub2: Main, IWorkAttached
{}
[BsonDiscriminator(SubType.Sub3)]
public class Sub3: Main
{}
public interface IWorkAttached
{
public string WorkId {get; set;}
}
我有更新实体的方法:
public void Update(IWorkAttached entity)
{
var col = _db.GetCollection<IWorkAttached>("ColName");
var updDefinition = Builders<IWorkAttached>.Update
.Set(t => t.Name, entity.Name)
.Set(t => t.Address, entity.Address)
.Set(t => t.WorkId, entity.WorkId) // interface property
col.UpdateOne(t => t.Id == entity.Id, updDefinition)
}
我们的想法是有一种方法可以更新两种类型的实体(Sub1
和Sub2
)然后我可以将它用于两个实体:
var sub1 = new Sub1 {...};
var sub2 = new Sub2 {...};
Update(sub1);
Update(sub2);
但是,它不起作用。我得到以下异常:
{document} .Id不受支持。
如果我在Update
方法中使用特定类型而不是接口,那么一切正常。是否有可能以这种方式使用mongo驱动程序?
堆栈跟踪:
at MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(Expression expression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.MongoCollectionImpl`1.ConvertWriteModelToWriteRequest(WriteModel`1 model, Int32 index)
at System.Linq.Enumerable.<SelectIterator>d__154`2.MoveNext()
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.BatchHelper.<FindOrderedRuns>d__8.MoveNext()
at MongoDB.Driver.Core.Misc.ReadAheadEnumerable`1.ReadAheadEnumerator.MoveNext()
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.BatchHelper.<GetBatches>d__6.MoveNext()
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.<ExecuteAsync>d__39.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.OperationExecutor.<ExecuteWriteOperationAsync>d__3`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.MongoCollectionImpl`1.<ExecuteWriteOperationAsync>d__62`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.MongoCollectionImpl`1.<BulkWriteAsync>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.MongoCollectionBase`1.<UpdateOneAsync>d__47.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
答案 0 :(得分:1)
我遇到了同样的问题。在MongoDB代码中调试之后,我看到在使用接口而不是特定类型时应用了不同的序列化器。在这种情况下, DiscriminatedInterfaceSerializer 用作接口的序列化器,而 BsonClassMapSerializer 用于特定类型。
使用此接口的序列化程序,实现类的类映射不链接到接口。因此,我不知道Id是bson id字段,应该映射到&#39; _id&#39;键。这就是引发异常的原因。
对我有用的解决方案是使用 ImpliedImplementationInterfaceSerializer :
[BsonSerializer(typeof(ImpliedImplementationInterfaceSerializer<IEntity, Entity>))]
public interface IEntity
{
// snip...
}
此属性注册序列化程序并定义为IEntity使用Entity的bson类映射,以便正确映射Id属性。 感谢@Robert Baker在答案中找到了这个解决方案:Deserialize object as an interface with MongoDB C# Driver
答案 1 :(得分:1)
我在项目中遇到了同样的问题,但是在另一种方法中,我的解决方案是编写完整的过滤器,而不是使用t => t.Id == entity.Id
:
var filter = Builders<Account>.Filter.Eq("_id", new ObjectId(accountId));
account = _accountsCollection.Find(filter).First();
答案 2 :(得分:1)
确保您的媒体资源中有 date price priceEUR
1 2019-12-21 140 155.358
2 2019-10-25 91 100.7734
3 2019-10-24 91 100.7643
4 2019-12-13 70 77.56
,这是我的问题。
答案 3 :(得分:0)
仅供参考,此处同样的问题是由于Lambda表达式中使用的数据类型不受支持或表达式复杂。
var awakenUsers = await _db.Get<DataEntity.UserProfile>(u
=> validInviteeMobs.Contains(u.MobNo)
&& (DateTime.UtcNow - u.LastAccessTime) >= new TimeSpan(72, 0, 0));
System.InvalidOperationException:(11/27/2018 05:20:37-{document} {LastAccessTime})不支持。 在MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(表达式表达式)
将其更改为示例后:
var awakenDeadline = DateTime.UtcNow.AddHours(-72);
var awakenUsers = await _db.Get<DataEntity.UserProfile>(u
=> validInviteeMobs.Contains(u.MobNo)
&& u.LastAccessTime <= awakenDeadline);
效果很好
答案 4 :(得分:0)
由于某种原因,当我将结构更改为类时遇到了这个问题,是的,调用类/结构的方法实现了一个接口。通过改回结构来解决它。
答案 5 :(得分:0)
就我而言,我覆盖了 Equals 运算符。 Mongo 不喜欢这样,所以只需将它移到 lambda 中就可以了。 干杯!
public class User : EntityBase
{
public Guid OrganizationID { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public override bool Equals(object obj)
{
if (obj is User user)
return this.ID == user.ID
|| string.Equals(this.UserName, user.UserName, StringComparison.InvariantCultureIgnoreCase);
return false;
}
}
public async Task<User> SaveUser(User user)
{
var repo = _crudRepositoryFactory.Get<User>();
var exisitngUser = await repo.First(x => x == user);
if (exisitngUser == null)
{
await repo.Create(user);
return user;
}
var res = await repo.Update(user, x => x == user);
return res.Item2;
}
我改成
public async Task<User> SaveUser(User user)
{
var repo = _crudRepositoryFactory.Get<User>();
var exisitngUser = await repo.First(x => x.ID == user.ID
|| (x.UserName == user.UserName && x.OrganizationID == user.OrganizationID));
if (exisitngUser == null)
{
await repo.Create(user);
return user;
}
var res = await repo.Update(user, x => x.ID == user.ID
|| (x.UserName == user.UserName && x.OrganizationID == user.OrganizationID));
return res.Item2;
}