XPO 使用记录

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
原文地址:https://www.cnblogs.com/asyuras/p/691357.html