public class Student : Entity
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Teacher : Entity
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Grade : RefEntity
{
public string Name { get; set; }
}
public class School : Entity
{
public string Name { get; set; }
public List Students { get; set; }
public List Teachers { get; set; }
public MongoDBRef Master { get; set; }
}
public class School : Entity
{
public string Name { get; set; }
public List Students { get; set; }
public List Teachers { get; set; }
public MongoDBRef Master { get; set; }
}
而这种设计,MongoDBRef的数据结构则过于简单,只有Id, CollectionName,DatabaseName三个字段,如果要得到Master,只能去Teacher集合中再次执行查询操作。
而本次提交,解决的正是这个问题,使代码可以写成如school.Pick(student.Id).Name的形式。
主要接口:IRefEntity,IDBRefContainer。
IRefEntity:为减少数据冗余,并提供一个Update方法。Update方法的逻辑是先保存当前实体,即执行IEntity.Save(),然后对DBRefs中的数据进行保存,接口定义如下:
public interface IRefEntity : IEntity
{
///
/// list of MongoDBRef
///
List DBRefs { get; set; }
///
/// save IEntity first, then save list of MongoDBRef
///
void Update();
}
IDBRefContainer接口,为IRefEntity.DBRefs的数据提供一个对应的实体容器,已完成相应的查询、添加、删除操作,接口定义如下:
public interface IDBRefContainer
{
bool Exists(string id);
bool Exists() where T : IEntity;
bool Exists(Predicate match) where T : IEntity;
T Pick(string id) where T : IEntity;
T Pick(Expression where) where T : IEntity;
List GetAll() where T : IEntity;
List GetMany(Expression where) where T : IEntity;
void Add(T entity) where T : IEntity;
void Add(List entities) where T : IEntity;
int Remove(Expression where) where T : IEntity;
void Remove(T entity) where T : IEntity;
void Remove() where T : IEntity;
int Count() where T : IEntity;
int Count(Expression where) where T : IEntity;
List GetAll();
}
需要注意的是,尽量使用IEntity.Save()进行保存操作,而减少使用IDBRefEntity.Update()进行更新保存 操作,因为IDBRefEntity.Update()针对的是所有IDBRefContainer中的数据,其执行效率还有待改善和提高。本人也一直在纠结,这个IDBRefEntity.Update()是否需要或者是否应该提供。
下面给出一个具体的测试用例:
[TestCase]
public void test()
{
grade = new Grade();
grade.Name = "No1";
foreach (Student student in students)
grade.Add(student);
foreach (Teacher teacher in teachers)
grade.Add(teacher);
grade.Update();
students[2].Name = "NameChanged";
students[2].Save();
var g = MongoEntity.Get(grade.Id);
Assert.AreSame(students[2].Name, grade.Pick(students[2].Id).Name);
Assert.AreNotSame(grade.Pick(students[2].Id).Name, g.Pick(students[2].Id).Name);
Assert.AreEqual(grade.Count(), g.Count());
Assert.AreEqual(grade.Count(), g.Count());
}
具体请参考源码
本人深感能力不足,欢迎大家指正、指教。