public class Person
{
public Person(string name)
{
Name = name;
}
public ObjectId Id { get; private set; }
public string Name { get; private set; }
public Person ChangeName(string name)
{
Name = name;
return this;
}
}
var person = new Person("丁丁");
MongoCollection<Person> persons = database.GetCollection<Person>(typeof(Person).Name);
persons.Insert(person);
person.ChangeName("丁丁2");
persons.Save(person);
如上所示,有一个Person的类,创建一个Person实例,插入到mongo里,然后执行Person的方法,将改变了属性的Person实例保存到mongo里,这是最简单的Mongo用法。
public class Person
{
public Person(string name)
{
persons = CollectionFactory<Person>.GetCollection();
Name = name;
persons.Insert(this);
}
MongoCollection<Person> persons;
public ObjectId Id { get; private set; }
public string Name { get; private set; }
public Person ChangeName(string name)
{
Name = name;
persons.Save(this);
return this;
}
}
Person中内置了Mongo集合通过工厂注入的实例,于是Person就可以这么用了:
var person = new Person("丁丁");
person.ChangeName("丁丁2");
好,到这儿,一切都很顺利。不过Person是个信息量很少很简单的对象。如果Person是一个结构非常复杂的对象,每次使用persons.Save(this),是将整个对象更新,非常占用网络流量,这样使用场景就很有限了。有没有什么改进的办法,比如Save(this)变成将有改动的属性更新掉?
//有更新才处理
if (allChanges.Count > 0)
{
updates = MongoDB.Driver.Builders.Update.Combine(allChanges);
collection.Update(query, updates);
}
foreach (IMongoUpdate up in allChangesForDelete)
{
collection.Update(query, up);
}
}
写一个类似Collection的泛型类,提供集合类操作,在操作末尾对对象的实例动态织入:
/// <summary>
/// 创建代理
/// </summary>
/// <param name="aggregateRoot"></param>
/// <returns></returns>
T_AggregateRoot CreateProxy(T_AggregateRoot aggregateRoot)
{
var aggregateRootType = aggregateRoot.GetType();
var constructor = aggregateRootType.GetConstructors().OrderBy(c => c.GetParameters().Length).First();
var parameters = constructor.GetParameters().Select(p => default(object)).ToArray();
return (T_AggregateRoot)proxyGenerator.CreateClassProxyWithTarget(aggregateRootType, aggregateRoot, parameters, new DataInterceptor<T_AggregateRoot>(this.Update, this.Remove));
}
最终,这一系列思路的产物就是一个聚合跟集合:
/// <summary>
/// 聚合根泛型集合类
/// </summary>
public class AggregateRootCollection<T_AggregateRoot> where T_AggregateRoot : class
{
...
}
然后用法类似这样:
var persons = new AggregateRootCollection<Person>("TestDb");
var personProxy = persons.Add(new Person("丁丁"));
personProxy.ChangeName("丁丁2");
第一行实例化聚合跟集合,第二行用Add方法对新的实例进行动态织入返回代理,第三行就是神奇的执行方法后,状态的变化就立刻持久化了。