我正在尝试实现这样的BaseRepository:
public interface IRepository<T>
{
Task<T> Update(T entity, IEnumerable<UpdateFieldDefinition> update);
}
public class BaseRepository<T> : IRepository<T> where T : BaseEntity{
}
有了BaseEntity,这是一个简单的类,用于存储在mongo中的所有实体。
由于将通过接口在核心项目内部调用资源库,并且核心项目必须不知道DB的实现是MongoDb,因此我使用了一个对象来传递给Update
,该对象称为UpdateFieldDefinition
的定义如下:这个:
public class UpdateFieldDefinition
{
public UpdateFieldDefinition(string propertyName, object propertyValue)
{
PropertyName = propertyName;
PropertyValue = propertyValue;
}
public string PropertyName { get; set; }
public object PropertyValue { get; set; }
}
因此,当我需要更新角色时,我将执行以下操作:
var updateFields = new List<UpdateFieldDefinition>();
var newNameValue = "Test";
var newListValue = new List<string> { "1", "2" };
updateFields.Add(new UpdateFieldDefinition("Name", newNameValue));
updateFields.Add(new UpdateFieldDefinition("ListValues", newListValue));
var testObj = await testRepository.Update(updateEntity, updateFields);
Update的实现是这个
public async Task<T> Update(T entity, IEnumerable<UpdateFieldDefinition> updateFieldDefinitions)
{
var builder = new UpdateDefinitionBuilder<T>();
var options = new FindOneAndUpdateOptions<T>
{
ReturnDocument = ReturnDocument.After,
IsUpsert = false
};
//setting the fields to update based on what has been set from outside based on the Implemented BaseEntity T
var updates = updateFieldDefinitions
.Select(updateFieldDefinition =>
builder.Set(updateFieldDefinition.PropertyName, updateFieldDefinition.PropertyValue))
.ToList();
//add update for LastModifiedDate =>
updates.Add(builder.Set(x => x.LastModifiedDate, DateTime.Now));
var filter = Builders<T>.Filter.Eq(en => en.Id, entity.Id);
var updateCmd = builder.Combine(updates);
var result = await DbContext.GetCollection<T>().FindOneAndUpdateAsync(filter, updateCmd, options);
return result;
}
但是这不起作用,因为当它遇到作为列表的“ ListValue”时,但是在UpdateFieldDefinition内存储为Object时,系统正在尝试将其转换为字符串,从而出现以下错误:{{1} }
有什么办法可以解决这个问题?给出的代码是问题的简化版本,因为我为BaseEntity创建了扩展方法,该方法将通过对T类型的所有属性的反射来创建UpdateFieldDefinition的列表。
// EDIT1 添加了我如何为实体检索UpdateFieldDefinitions列表的示例
Cannot deserialize a 'List<String>' from BsonType 'String'.
答案 0 :(得分:0)
public static UpdateDefinition<T> GetUpdateDefinition<T>(this T entity)
{
var updateFieldDefinitions = entity.GetType().GetProperties()
.Where(x => !new string[] { "Id", "_id" }.Contains(x.Name))
.Select(x => new UpdateFieldDefinition(x.Name, x.GetValue(entity)));
var builder = new UpdateDefinitionBuilder<T>();
var updates = updateFieldDefinitions.Select(TField => builder.Set(TField.Name, TField.Value));
return builder.Combine(updates);
}
...
public async static Task<T> UpsertAsync<T>(Expression<Func<T, bool>> expression, T entity)
{
var collection = Database.GetCollection<T>(typeof(T).Name);
var updates = entity.GetUpdateDefinition();
var options = new FindOneAndUpdateOptions<T>
{
ReturnDocument = ReturnDocument.After,
IsUpsert = true
};
return await collection.FindOneAndUpdateAsync(expression, updates, options);
}