在WinForms应用程序中使用对象关系映射(ORM)模型已经有一段时间了。最近,需要为ASP.NET应用程序开发,很快就对ObjectDataSource感到非常沮丧。不想就DataSet和集合之间进行辩论。简而言之,使用强类型集合。
当使用非平面(层次化)领域模型时,无法绑定到复杂属性。例如,在下面的领域模型中,需要在课程列表中显示Instructor的FullName,然后能够编辑它。然而,虽然可以绑定到Instructor,但它会显示Person的toString()方法中的任何内容。这对于显示来说是可以的,但编辑呢?可以实施IConvertible
这种方法还带来了许多其他优势。ObjectDataSource在没有大量管道的情况下不会很好地排序或分页。当绑定到DataTable时,它会本地处理,因此不需要编写额外的代码。
由于Course没有显示属性"InstructorId"、"InstructorFullName"或"AvailableSlots",可以将它们混合到数据类型中,就好像它们是类的一部分一样。像Ruby和Python这样的动态语言允许在对象级别上这样做,从而消除了在转换中这样做的需要。C#3(和VB9)有所谓的扩展方法,但到目前为止还没有提到扩展属性(数据绑定需要)。
public static DataTable FindAll()
{
DataTableAdapter dta = new DataTableAdapter();
dta.AddColumn("InstructorId", typeof(string), delegate(Course c) { return c.Instructor.Id; });
dta.AddColumn("InstructorFullName", typeof(string), delegate(Course c) { return c.Instructor.FullName; });
dta.AddColumn("AvailableSlots", typeof(string), delegate(Course c) { return c.MaxStudents - c.Students.Count; });
return dta.GetDataTable(CourseService.FindAll());
}
这里大量使用了反射。这可能会导致一些性能问题,具体取决于使用的对象基础有多大。
PropertyInfo[] pi = typeof(T).GetProperties();
Type piType;
for (int i = 0; i < pi.Length; i++)
{
piType = pi[i].PropertyType;
if (piType.IsGenericType && piType.GetGenericTypeDefinition() == typeof(Nullable<>))
piType = Nullable.GetUnderlyingType(piType);
dt.Columns.Add(new DataColumn(pi[i].Name, piType));
}