XPO 学习笔记(一)
XPO 使用记录
XPO 使用记录
http://www.rainsts.net/article.asp?id=50
1. 一般实体类直接继承自 XPObject,如果需要自定义主键或自增字段则可继承自XPCustomObject。
2. 继承自XPBaseObject的实体类,Delete后将被直接物理删除。而XPCustomObject & XPObject的继承类则是软删除。
(1) 实体对象软删除
customer.Delete();
customer.Save();
(2) 物理删除
Session.DefaultSession.PurgeObject(customer);
(3) 物理删除所有被标记软删除的记录。
Session.DefaultSession.PurgeDeletedObjects();
(4) 清除数据库中所有数据。
Session.DefaultSession.ClearDatabase();
(5) 恢复被软删除的记录。
while(true)
{
o = (MyObject)Session.DefaultSession.FindObject(typeof(MyObject), new NotOperator(new NullOperator("GCRecord")), true);
if (o == null)
{
break;
}
o.GCRecord = null;
o.Save();
}
(6) 批量删除
XPCollection customers = new XPCollection(typeof(Product), new BinaryOperator("Customer", "Tom"));
Session.DefaultSession.Delete(customers);
Session.DefaultSession.Save(customers); // persist deletion 我的1.58版本Session.Save()没有重载这个方法????
3. 继承自XPCustomeObject的类必须使用KeyAttribute指定主键,且只能指定一个字段(??????)。
public class Customer : XPCustomObject
{
[Key]
public string Name;
}
4. 指定字段的类型和大小。
public class Customer : XPObject
{
[Size(20)]
public string Name;
[DbType("nvarchar(6)"]
public string Postcode;
[DbType("Text")]
public string Summary;
}
5. 字段验证。缺省情况下我们使用 public field 来公开字段,改用 public property 就可以实现字段赋值验证。
public class Customer : XPObject
{
private string postcode;
public string Postcode
{
get { return postcode; }
set
{
// ... 验证代码省略...
postcode = value;
}
}
}
6. 只读字段。缺省情况下XPO只为可写的公开字段或属性创建字段,我们可以通过PersistentAttribute属性来创建只读字段。NonPersistentAttribute作用则相反,表示该字段或属性不写入数据库。
public class Customer : XPObject
{
[Persistent]
public DateTime Date
{
get { return DateTime.Now; }
}
[Persistent("Date")]
private DateTime date;
}
7. 一对多。下面的演示代码,每个消费者有多条收货地址。
"CustomerAddress" 关系名称。
"Aggregated" 级联操作(删除、更新)。
"Addresses" 集合属性名。
public class Customer : XPObject
{
public string Name;
[Association("CustomerAddress", typeof(Address)), Aggregated]
public XPCollection Addresses
{
get { return GetCollection("Addresses"); }
}
}
public class Address : XPObject
{
[Association("CustomerAddress")]
public Customer Customer;
}
8. 一一对应时,不会自动创建其对应对象。
public class Customer : XPObject
{
public Customer()
{
// Do not place any code here.
}
public Customer(Session session) : base(session)
{
// Do not place any code here.
}
public Address Address;
public override void AfterConstruction()
{
base.AfterConstruction();
// Initialize object properties here
Address = new Address();
}
...
}
9. 多对多。每个消费者拥有多个类型,每个类型又包含消费者。
注意两个类中关系名相同。
public class Customer : XPObject
{
public string Name;
[Association("CustomerType", typeof(Type)), Aggregated]
public XPCollection Types
{
get { return GetCollection("Types"); }
}
}
public class Type : XPObject
{
[Association("CustomerType", typeof(Customer))]
public XPCollection Customers
{
get { return GetCollection("Customers"); }
}
}
10. 延迟字段。DelayedAttribute属性让字段只有在被操作的时候才载入数据,比较适合操作大数据字段。
public class Goods: XPObject
{
public string Name;
public decimal Price;
public string CatalogId;
...
private XPDelayedProperty image1 = new XPDelayedProperty();
[Delayed("image1")]
public Byte[] Image1
{
get { return (Byte[])image1.Value; }
set { image1.Value = value; }
}
}
11. 分页。注意XPO的XPCursor的作用是分页缓存,而并非我们一般情况下说的分页。和XPCollection不同,XPCursor每次只将指定数目(PageSize)的实体对象载入内存,当我们枚举操作(IEnumerable)的对象超出当前缓存,则自动读取下一页继续操作,这种方法比XPCollection要节省内存。正因为如此,XPCursor只提供了foreach单向循环操作,而不能使用索引器的方式获取实体对象。至于我们平常所用的分页方法,可以使用XPPageSelector基于XPCollection实现。
12. 连接 SQL Server
Session.DefaultSession.Connection = new System.Data.SqlClient.SqlConnection("server=(local);uid=sa;pwd=;database=test");
Session.DefaultSession.AutoCreateOption = AutoCreateOption.SchemaOnly;
13. NullValueAttribute 属性只是当字段等于某个特定值时,写入数据库时将值替换为DBNull。而获取时,如果值为DBNull,则使用该指示值替代。
public class Customer : XPObject
{
public string Name;
[NullValue("unknown email!")]
public string Email;
}
14. IndexedAttribute 索引字段
public class Customer : XPObject
{
[Indexed(Unique = true)] // 无重复索引. "[Indexed]" 有重复索引。
public string Name;
}
15. XPObject.Reload()只刷新当前对象的属性,不刷新其关联子对象的属性。
16. 监视XPO自动生成SQL。在app.config 中增加下面的配置。1.58我测试无效。?????
[XML]
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="LogFileTraceListener" type="System.Diagnostics.TextWriterTraceListener"
initializeData="trace.log" />
<remove name="Default" />
</listeners>
</trace>
<switches>
<add name="XPO" value="3" />
</switches>
</system.diagnostics>
</configuration>
17. ExplicitLoadingAttribute可以指定多层引用的递归层数,以减少数据库查询,提高性能。
class A : XPObject
{
public string Name = "A";
}
class B : XPObject
{
public string Name = "B";
[ExplicitLoading(3)]
public A A;
}
class C : XPObject
{
public string Name = "C";
[ExplicitLoading]
public B B;
}
class D : XPObject
{
public string Name = "D";
[ExplicitLoading]
public C C;
}
class E : XPObject
{
public string Name = "E";
public D D;
}
缺省情况下,我们检索到E对象时,系统会自动获取(构造)其引用的对象,当引用层数很深时,就会产生多条SQL语句。此时我们可以使用[ExplicitLoading]属性合并多个查询。在上面的例子中,D被做了属性标记,那么会自动往下递归查找有该标记的引用。因此会将 D、C、B的查询构造到同一条SQL语句中,而A依然会被单独构造SQL,我们可以将B中的属性标记加上参数3,就可以将A也加到递归中,如此D、C、B、A合并到同一条SQL语句中。注意这个Depth参数表示所引用类型距离Root的深度,A距离E有3层。
18. 多ASP.net Application中使用XPO,DevExpress推荐方案是为每个Request创建一个Session,也就是说:
Stateless + Session for each Request + Connection Pool