回答晚了,但是这就是您在没有字符串的情况下执行它的方法。如果您修改属性,则代码将无法编译。第一次在生产代码中使用表达式尝试!他们太棒了!
模型:
class Phone
{
public string _id { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public List<Line> Lines { get; set; }
}
class Line
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
}
代码:这是我创建更新语句的方式,不依赖于字符串。
var update = new UpdateDocument<Phone>();
// set filter
update.SetFilter(x => x._id == "123456789");
update.AddValueToUpdate(p => p.Name, "New Name");
update.AddValueToUpdate(p => p.Lines[0].Name, "Line 1");
update.AddValueToUpdate(p => p.Lines[1].Name, "Line 2");
update.AddValueToUpdate(p => p.DateCreated, DateTime.UtcNow);
var updateQuery = update.Build();
这就是所需传递给mondo进行更新的内容!
{ "_id" : "123456789" },
{$set:
{"Name":"New Name","Lines.0.Name":"Line 1","Lines.1.Name":"Line 2","DateCreated":ISODate("2021-04-30T16:04:59.332Z")}
}
如果您希望该代码在此处正常工作,则需要使用辅助类:
using MongoDB.Bson;
using System.Linq.Expressions;
using MongoDB.Bson.Serialization;
class UpdateDocument<T>
{
private string _filter;
private List<KeyValuePair<string, object>> _valuesToUpdate { get; set; } = new List<KeyValuePair<string, object>>();
public void SetFilter(Expression<Func<T, bool>> filterDefinition)
{
var documentSerializer = BsonSerializer.SerializerRegistry.GetSerializer<T>();
var where = Builders<T>.Filter.Where(filterDefinition).Render(documentSerializer, BsonSerializer.SerializerRegistry);
_filter = where.ToJson();
}
public void AddValueToUpdate(string name, object value)
{
_valuesToUpdate.Add(new KeyValuePair<string, object>(name, value));
}
public void AddValueToUpdate(Expression<Func<T, object>> name, object value)
{
var memberExpression = name.Body as MemberExpression;
if (memberExpression == null)
{
var unaryExpression = name.Body as UnaryExpression;
if (unaryExpression != null && unaryExpression.NodeType == ExpressionType.Convert)
memberExpression = unaryExpression.Operand as MemberExpression;
}
var result = memberExpression.ToString();
result = result.Substring(result.IndexOf('.') + 1);
if (result.Contains("get_Item"))
result = Regex.Replace(result, @"(?x) get_Item \( (\d+) \)", m => $"{m.Groups[1].Value}");
AddValueToUpdate(result, value);
}
public string Build()
{
if (_valuesToUpdate.Any() == false)
{
return null;
}
StringBuilder sb = new StringBuilder();
sb.Append(_filter);
sb.Append(',');
sb.Append("{");
{
sb.Append("$set:{");
foreach (var item in _valuesToUpdate)
{
sb.Append('"');
sb.Append(item.Key);
sb.Append('"');
sb.Append(':');
var value = BsonExtensionMethods.ToJson(item.Value);
sb.Append(value);
sb.Append(',');
}
sb.Length--;
sb.Append('}');
}
sb.Append("}");
return sb.ToString();
}
}