迟到的答案,但这是你在没有字符串的情况下如何做到的。如果您修改您的属性代码将无法编译。第一次在生产代码中使用表达式尝试!他们真棒!
楷模:
class Phone
{
public string _id { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
// Contain multiple lines as subdocument
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>
{
/// <summary>
/// _id of document to update.
/// </summary>
private string _filter;
/// <summary>
/// Example:
/// FirstName, Antonio
/// Education.Elementary.Year, 2004
/// </summary>
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)
{
// nothing to update
return null;
}
/*
update({
_id: 7,
"comments._id": ObjectId("4da4e7d1590295d4eb81c0c7")
},{
$set: {"comments.$.type": abc}
}, false, true
);
*/
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(',');
}
// remove last comma
sb.Length--;
sb.Append('}');
}
sb.Append("}");
return sb.ToString();
}
}