为什么我访问某实体对象的OriginalData的属性为空
首先,看OriginalData对象的ID,如果为0,表示是一个空对象,所有的属性为默认值,请参考OriginalData刷新的时机判断这个访问操作是不是新建,这个对象是标准的查询出来的还是通过CopyTo的方式构造的(实体基类的CopyTo不涉及OriginalData)
如果OriginalData有有效的ID,检查这个对象的加载方式,看看是不是特殊的加载方式引起属性为空
OriginalData的关联对象
OriginalData 和CopyTo方法很类似,只完整实现了对基本属性的拷贝,对于关联实体,实际上是不拷贝的,这样,出现aEntity.OriginalData.bEntity的访问方式,对bEntity,是懒加载上来的
实体的状态SysState
实体的状态,为枚举对象,开发人员主要关心以下4个枚举值:Inserted,Updated,Deleted,Unchanged,分别对应实体的新建,修改,删除,不变化(查询返回的初始状态)
是否需要持久化NeedPersistable
NeedPersistable表示这个对象是否需要持久化,如果为false,则这个对象将不会参与持久化
Session
基本概念和使用方式
在现在UBF中,Session的本意是work unit,即持久层的一个边界,非常轻,主要用作批量提交,并标识这次批量提交的边界。在session里面的CUD操作会受持久层控制,而seesion 外实体是不受控制的,所以,做CUD操作要在session里面完成,一般建议一个BP调用最好都有一个大session包住,这样,在里面的操作就不用多次开Session,性能会好些
关于事物,session仅仅是一个持久层边界,不涉及到事务等概念,目前UBF的事物支持在AOP上定义,可以在BP上设置
当发生session嵌套的情况时,每次提交都是真正提交
using (ISession session1 = Session.Open ()){
...
using (ISession session2 = Session.Open ()){
...
19400bd7240c844769eaee2fmit(); //提交更改,但只是Session2范围内的修改更新 }
19400bd7240c844769eaee2fmit(); //提交更改,只处理Session1的修改更新
}
当前ISession可以通过Session的Current属性获得,每调用一次Session的Open方法,Current属性都会被更新
在一个Session范围内,可以分步提交,
using(ISession session1 = Session.Open ()){
Ass1to1 objA1 = A_Ass1to1.Create();
19400bd7240c844769eaee2fmit(); //提交objA1的新建动作
Ass1to1 objA2 = A_Ass1to1.Create();
19400bd7240c844769eaee2fmit();//提交objA2的新建动作
}
对外接口
Create(IEntity entity)
将entity对象的状态设置为UFSoft.UBF.PL.Engine.ObjectState.Inserted,并加入到当前的session中
Modify(IEntity entity)
将entity对象的状态设置为UFSoft.UBF.PL.Engine.ObjectState. Updated,并加入到当前的session中
Remove(IEntity entity)
如果当前session有这个entity,且状态为insert,则从当前session中移出这个对象,其他情
况下,将entity对象的状态设置为UFSoft.UBF.PL.Engine.ObjectState. Deleted,并加入到当前的session中
InList(IEntity entity)
将entity加入到当前的session中
objA = A_Ass1to1.Create();
19400bd7240c844769eaee2f_A_1to1 = "Test";
using (ISession s = Session.Open())
{
s.InList(objA);
19400bd7240c844769eaee2fmit();
}
Assert.IsNotNull(A_Ass1to1.Finder.Find("ID = '" + objA.ID + "'"));
DeList(IEntity entity)
将entity从session中移出
using (ISession s = Session.Open())
{
objA = A_Ass1to1.Create();
objA.Code_A_1to1 = 333;
s.DeList(objA);
19400bd7240c844769eaee2fmit();
}
Assert.IsNull(A_Ass1to1.Finder.Find("ID = '" + objA.ID + "'")); 实体的操作
增加实体
简单实体:
模型如下,对实体A操作
◆常规做法:
通常我们新建实体是要求在session里面建立:
using (ISession session = Session.Open())
{
obj = A_Ass1to1.Create();
...
19400bd7240c844769eaee2fmit();
}
◆特殊做法:
遇到一些特殊情况,需要在session外面new一个对象时。这种做法很特殊,需要显式在一进入sesssion时调用session.Create(obj),不推荐
A_Ass1to1 obj = new A_Ass1to1();
using (ISession session = Session.Open())
{
//一进入session,操作对象之前(包括设置实体的状态,赋值等所有的相关的操作之前)
//要显示调用session.Create(obj)
session.Create(obj);
obj.ID = 111;
19400bd7240c844769eaee2f_A_1to1 = "aaa";
19400bd7240c844769eaee2fmit();
}
主从实体:
◆1对1,其中A_Com1c1为主实体,B_Com1c1为非主实体,注意红字的写法
A_Com1c1 objA;
B_Com1c1 objB;
using (ISession session = Session.Open())
{
objA = A_Com1c1.Create();
objA.Code_A_Com1c1 = 1000;
19400bd7240c844769eaee2f_A_Com1c1 = "objA";
objB = B_Com1c1.Create(objA);
objB.Code_B_Com1c1 = 1001;
19400bd7240c844769eaee2f_B_Com1c1 = "objB";
19400bd7240c844769eaee2fmit();
}
◆1对多:其中A_Com1cN为主实体,B_Com1cN为非主实体,注意红字的写
法。对于非主实体,有两种新建方式,这两种方式都只支持
A_Com1cN objA;
B_Com1cN objB;
using (ISession session = Session.Open()) {
objA = A_Com1cN.Create();
objA.Code_A_Com1cN = 111;
//方式一
objB = B_Com1cN.Create(objA);
objB.Code_B_Com1cN = 222;
objB = B_Com1cN.Create(objA);
objB.Code_B_Com1cN = 333;
//方式二
objB = objA.B_Com1cN.AddNew();
objB.Code_B_Com1cN = 444;
objB = objA.B_Com1cN.AddNew();
objB.Code_B_Com1cN = 555;
19400bd7240c844769eaee2fmit();
}
查询实体
(关于OQL和参数的用法,见实体查询这个章节)
查单个实体:下面的操作为查询一条ID为“111”的纪录
FindByID方法是先从缓存里面取,缓存没有再去数据库取,
A_Com1cN obj = A_Com1cN.Finder. FindByID(111);
Find方法是直接从数据库取
A_Com1cN objA = A_Com1cN.Finder.Find("ID = 111");
查实体集合
FindAll方法是直接从数据库取,参数为OQL语句
A_Com1c1.EntityList list = A_Com1c1.Finder.FindAll("");
修改实体
简单实体
◆常规做法
通常我们修改实体是要求在session里面建立
using(ISession session = Session.Open ()){
Customer obj = Customer.Finder. FindByID(id);
if(obj!=null){
19400bd7240c844769eaee2f = "new name";
}
... ...
19400bd7240c844769eaee2fmit();
}
◆特殊做法
遇到一些特殊情况,需要外面传进的实体时,需要显式调用session.
Modify(obj),不推荐
using (ISession session = Session.Open())
{
session.Modify(obj);
19400bd7240c844769eaee2fmit();
}
主从实体:
◆1对1
◆1对多
using (ISession session = Session.Open())
{
objA = A_Com1cN.Finder.Find("ID = '" + objA.ID + "'", null);
B_Com1cN.EntityList bList = objA.B_Com1cN;
bList[0].Name_B_Com1cN = "aaa";
bList[1].Name_B_Com1cN = "bbb";
19400bd7240c844769eaee2fmit();
}
删除实体
简单实体
using(ISession session = Session.Open ()){
Customer obj = Customer.Finder.FindByKey(id);
if(obj!=null){
obj.Remove();
}
... ...
19400bd7240c844769eaee2fmit();
}
主从实体:
删主实体会自动全部删除从实体
using (ISession session = Session.Open())
{
objA = A_Com1cN.Finder.Find("ID = '" + objA.ID + "'", null);
//会自动删除objA及objA下所有的从实体
objA.Remove();
19400bd7240c844769eaee2fmit();
}
只删除从实体:
删除从实体有两种方式,一种是调用从实体的objA.B_Com1cN.RemoveAt(0),一种是调用objA.B_Com1cN.Remove(b),这两种方式是等价的
using (ISession session = Session.Open())
{
objA = A_Com1cN.Finder.Find("ID = '" + objA.ID + "'", null);
B_Com1cN.EntityList bList = objA.B_Com1cN;
B_Com1cN b = bList[2];
objA.B_Com1cN.RemoveAt(0);
objA.B_Com1cN.Remove(b);
19400bd7240c844769eaee2fmit();
}
Q&A
◆对于一对多组合,我怎样知道删除的子对象
我们知道,对于一对多的情况,当我们对子对象调用Remove方法时,该对象会从当前的集合中移出,即子对象的集合存放的是有效的对象,是新建和修改的对
象。如果我们还需要访问删除的对象,可以从当前的List的属性DelLists中找到。
◆对一对多组合的子对象作集合Clear操作,怎么没有删除
需要注意,实体的删除动作只能用Remove方法,Clear是集合本身的方法,不是持久层提供的删除自对象的方法
实体的查询
BE的查询这块主要有3个查询类,EntityDataQuery,EntityQuery和EntityViewQuery,EntityDataQuery 主要用于希望返回结果是IDataReader,DataSet,单值的情况EntityQuery 主要用于希望返回的结果是实体,实体集合
EntityViewQuery 主要用于对视图的操作,与前2种不同的是,需要自己处理数据库的连接。EntityDataQuery
创建方式:
有2种方式创建EntityDataQuery
通过Entity对象:
EntityDataQuery q = Yel_Ass1to1_A.Finder.CreateDataQuery();
通过EntityFullName:
EntityDataQuery q = new EntityDataQuery("Association.Yel_1to1Self");
EntityDataQuery q = new EntityDataQuery(Yel_1to1Self.EntityRes.BE_FullName);
返回DataSet:FindDataSet
全OQL方式
DataSet ds = q.FindDataSet("select ID,Name,Code from Association::Yel_1to1Self");
条件OQL方式
DataSet ds = q.FindDataSet( "ID>1");
返回IDataReader:FindDataReader
全OQL方式
IDataReader dr = q.FindDataReader ("select ID,Name,Code from Association::Yel_1to1Self");
条件OQL方式
IDataReader dr = q.FindDataReader ( "ID>1");
返回单值:
q.FindValue("select Max(ID) where id > 111");
分页查询
DataSet ds = q.FindDataSetByPage(1, 2, " ID > @ID and Name = @mmm order by ID"); EntityQuery
创建方式:
有2种方式创建EntityQuery
通过Entity对象:
EntityQuery eq = Yel_Ass1to1_A.Finder.CreateQuery();
通过EntityFullName:
EntityQuery eq = new EntityQuery ("Association.Yel_1to1Self");
EntityQuery eq = new EntityQuery(Yel_Ass1to1_A.EntityRes.BE_FullName);
另外,以强类型的方式使用Yel_Ass1toN_A.Finder,其对外接口和功能与EntityQuery 类似,只是Yel_Ass1toN_A.Finder返回强类型的对象,EntityQuery返回弱类型的对象
返回实体:FindByID 和Find
FindByID ,先从缓存加载对象,如果缓存没有,则从数据库加载对象
Yel_Ass1toN_A a = Yel_Ass1toN_A.Finder. FindByID (a.ID);
Yel_Ass1toN_A a = (Yel_Ass1toN_A)eq.FindByID(a.ID);
Find方式,直接从数据库加载

