先介绍以下neo,通常的neo代码是这样的 IDataStore dataStore=new SqlDataStore(connectionString) //创建一个IDataStore实例,最好用factory 模式 ObjectContext objectContext=new ObjectContext(dataStore) //创建一个ObjectContext 实例 CustomerFactory factory=new CustomerFactory(objectContext) //创建一个具体对象的Factory类 ObjectList<Customer> customers=factory.FindAllObjects(); //执行查询 neo 让你编辑一个xml文件,然后根据这个文件自动生成entity,entityMap,entityFactory, xml文件的部分最后总是由具体的entityMap来描述的. 因此最终交付时并不需要交付xml 文件 neo 已经近一年没有更新了,最新的版本是在blog而不是在neo.codehaus.org 上发布的. 随着linq to sql和ado.net entity framework的发布,dataset(datatable)最终将会被他们所取代,但个人觉得的,从技术角度说,dataset 解决了许多问题,比方说,快速的装载,对象状态的跟踪,合并修改,更好的数据绑定等等, 如果有orm 建筑在dataset技术之上,也是不错的一个方案. 但是,我并没有发现这样的方式,neo也并没有完全发挥dataset的优势, 比方说 下面所说的3和4 btw : 最近看到的IdeaBlade DevForce是基于dataset技术的,它的entity是最终是从 DataRow继承下来的,但由于这个是商业项目,因此没有深究. 有兴趣的可访问 www.ideablade.com ,如果你是mvp ,你可以免费申请专业版. 1. neo 的entity是composite了DataRow ,但并不是继承DataRow,每个entity属性均使用datarow来存储,因此,entity的内存占用比一般常规的entity的小些. 2. neo 在内存中同时维持dataset和entity的,因此,相比仅使用数据集,内存占用还是大一些 3. neo 的ObjectList并不适合windows 绑定(确切的说这部分代码,实现IBindingList部分的没有完成) 4. neo 先是查询返回一个DataSet,然后将DataSet中每个表的记录导入到ObjectContext中的mainDataSet(DataSet属性)中,并创建每个对象,所以 ,它的性能大约就是直接使用dataset的2到3倍,注意, 创建对象时由于entitycompsoite了datarow,因此,每个对象只需要一次简单的赋值就行.所以,总体上看,性能还是比常规的entity要好一些. 5. neo 总是试图和dataset保持同步,当你执行一个查询,如 ObjectList<Customer> customers=new CustomerFactory(objectContext).FindAllObjects(); Customer对象所对应的数据表(以及其关系)的schema就会被导入到 ObjectContext的DataSet中,同时Customer所对应的数据表记录会被fill,如果你调用了一个关系,比方说 for(Order order in customers.Orders){ } Order对象所对应的数据表也会被fill 你创建一个对象,删除一个对象,这些对象对应的DataRow也会被相应的创建和删除 6. 说说ObjectContext的使用范围,在实际使用中,你应该将ObjectContext当成类似一个DataSet.一般来说,一个表单维护一个ObjectContet,比方说报价表单,维护一个quotationObjectContext,这样quotationObjectContext.DataSet将会仅包括报价有关的信息,如主表,明细表 ,相关的lookup记录等 7. 上面了说,在操作对象时neo 会同objectContext.DataSet保持同步,但反过来,操作objectContext.DataSet时,不会.但是你总可以将一个DataRow,DataSet合并到objectContext中. 这点对分布式操作非常重要. 8. 基于上一条,在windows form 中,你可以直接绑定objectContext.DataSet,但是,最好不要直接新增DataRow,创建一个entity,然后定位entity.Row (DataRow)是一个方法 9.neo 的机制非常适合分布式环境, 这这种情况下,你将ObjectContext区分为server端的和 client的 server端的ObjectContext ,总是获得一个具体的IDataStore实例,构造一个服务层,在两者之间传递dataset,clinet段的ObjectContext,则合并从服务层中获得的dataset ,然后提交更改的DataSet 10. neo 在内部维护着一个叫ObjectTable类的实例,这个实例跟踪所有的对象(包括删除的对象),在这里,ObjectId被作为key,ObjectId 是由dataTable 的表名和其primaryKey数组的值组成的. 这里有个主键的问题,主键最好是业务无关的,自动生成的,有些业务相关的并且依赖其它字段的主键是个棘手的问题.这同neo无关,不过如果你没有设置主键,这样,连续的两次新增就会有异常. (objectable 会找到上一条新增的记录,并且,同该记录的datarow会相同,结果引发类似下面的错误) protected virtual IEntityObject GetObjectForRow(DataRow aRow) if(eo.Row.Equals(aRow) == false) throw new InvalidOperationException("Internal inconsistency; object exists but references different row."); 通常的做法是阻止连续新增,每条记录检查完整性,我把它称为 每记录检查,批量更新.意思是每新增或编辑完一条记录(注意,这里只是保存到dattable或是对象列表中)检查完整性, 用户可以新增多条,编辑多条,然后一次性提交修改.在 界面上,主要在移动记录时,如上一条,下一条,新建,删除,和保存时检查当前记录的完整性. 由于是批量更新,在用户离开时要有提示 使用neo 时并不能真正忘掉dataset,比方说 ,你注册一个ColumnChanging事件,这里你需要知道datatable name和datacolumn name(neo通过ColumnChangeBroker 对象对单个列的ColumnChanging事件支持), 如果你不想在这个事件中处理数据行,你可以将获得该datarow的对象表示,如下面的例子customerBindingSource 绑定的是由ObjectContext提供的DataSet,GetObjectId是个Helper函数 public ObjectId GetObjectId(DataRow row) { object[] keys = new object[row.Table.PrimaryKey.Length]; foreach (DataColumn column in row.Table.PrimaryKey) { keys[0] = row[column]; } return new ObjectId(row.Table.TableName, keys); } private bool ValidateCurrent() { if (customerBindingSource.Current != null) { DataRowView drv = (DataRowView)customerBindingSource.Current; DataRow row=drv.Row; Shyechang.Data.Customer customer=(Shyechang.Data.Customer)clientObjectContext.GetObject(GetObjectId(row)); return customer.Validate(); } return true; } 默认生成时datatable name和datacolumn 的name是数据库的表名和列名. 你可以说这隔离的不可彻底. 看起来如果编码为entity 的名称和属性名 会好些,看起来这个可以通过修改一些代码来达成. |