7. 对象连接关系
对象之间有三种关联关系.它们分别是One-to-Many Relationships(一对多)
One-to-One Relationship(一对一) Many-to-many Relationship(多对多)
7.1 一对多
一对多是最常用的关联关系. 一个持久性对象A可以有多个关联的持久性对象B,但是持久性对象B仅有一个关联对象A.
public class TitleType : XPObject {
string _typeName;
[Size(50)]
public string typeName
{
set
{
SetPropertyValue<string>("typeName", ref _typeName, value);
}
get
{
return _typeName;
}
}
……
[Association(("TitleTypes"), typeof(Title))]
public XPCollection Titles { get { return GetCollection("Titles"); } }
……
}
public class Title : XPObject
{
string _TitleName;
[Size(50)]
public string TitleName
{
set
{
SetPropertyValue<string>("TitleName", ref _TitleName, value);
}
get
{
return _TitleName;
}
}
string _TitleContent;
public string TitleContent
{
set
{
SetPropertyValue<string>("TitleContent", ref _TitleContent, value);
}
get
{
return _TitleContent;
}
}
….
[Association("TitleTypes")]
public TitleType titleType;
……….
}
string _typeName;
[Size(50)]
public string typeName
{
set
{
SetPropertyValue<string>("typeName", ref _typeName, value);
}
get
{
return _typeName;
}
}
……
[Association(("TitleTypes"), typeof(Title))]
public XPCollection Titles { get { return GetCollection("Titles"); } }
……
}
public class Title : XPObject
{
string _TitleName;
[Size(50)]
public string TitleName
{
set
{
SetPropertyValue<string>("TitleName", ref _TitleName, value);
}
get
{
return _TitleName;
}
}
string _TitleContent;
public string TitleContent
{
set
{
SetPropertyValue<string>("TitleContent", ref _TitleContent, value);
}
get
{
return _TitleContent;
}
}
….
[Association("TitleTypes")]
public TitleType titleType;
……….
}
在这个例子,Association属性(AssociationAttribute) 应用于 TitleType .Titles 和Title.TitleTypes
在这里,Association 属性应用于TitleType .Titles 和Title.TitleTypes 属性去定义两者之间的联系. 当一个对象与另一个对象关联, 多的一方关联必须定义一个XPCollection 或者XPCollection<T > 类.
在使用中, 如果类只有一个连接,你可以省去 [Association] 属性, 例如:
[Association("TitleTypes")]
public TitleType titleType;
但是如果该类出了和Title类连接,它还与其他类关联,你必须指定该连接属性名取协助XPO解决关联.
7.2 一对一
当2个对象参与关联,它有一个属性去指向他们持久性对象. 它必须需要对Setter 方法编写额外的代码来确信他们关系的完整性. 下例中直接引用帮助中的例子
// Represents the Building class which refers to the building's owner.
public class Building : XPObject {
Person owner = null;
public Person Owner {
get { return owner; }
set {
if(owner == value)
return;
// Store a reference to the former owner.
Person prevOwner = owner;
owner = value;
if(IsLoading) return;
// Remove an owner's reference to this building, if exists.
if(prevOwner != null && prevOwner.House == this)
prevOwner.House = null;
// Specify that the building is a new owner's house.
if(owner != null)
owner.House = this;
OnChanged("Owner");
}
}
}
// Represents the Person class which refers to the person's house.
public class Person : XPObject {
Building house = null;
public Building House {
get { return house; }
set {
if(house == value)
return;
// Store a reference to the person's former house.
Building prevHouse = house;
house = value;
if(IsLoading) return;
// Remove a reference to the house's owner, if the person is its owner.
if(prevHouse != null && prevHouse.Owner == this)
prevHouse.Owner = null;
// Specify the person as a new owner of the house.
if(house != null)
house.Owner = this;
OnChanged("House");
}
}
}
public class Building : XPObject {
Person owner = null;
public Person Owner {
get { return owner; }
set {
if(owner == value)
return;
// Store a reference to the former owner.
Person prevOwner = owner;
owner = value;
if(IsLoading) return;
// Remove an owner's reference to this building, if exists.
if(prevOwner != null && prevOwner.House == this)
prevOwner.House = null;
// Specify that the building is a new owner's house.
if(owner != null)
owner.House = this;
OnChanged("Owner");
}
}
}
// Represents the Person class which refers to the person's house.
public class Person : XPObject {
Building house = null;
public Building House {
get { return house; }
set {
if(house == value)
return;
// Store a reference to the person's former house.
Building prevHouse = house;
house = value;
if(IsLoading) return;
// Remove a reference to the house's owner, if the person is its owner.
if(prevHouse != null && prevHouse.Owner == this)
prevHouse.Owner = null;
// Specify the person as a new owner of the house.
if(house != null)
house.Owner = this;
OnChanged("House");
}
}
}
7.3 多对多
class History : XPObject
{
string _historyName;
[Size(50)]
public string historyName
{
set
{
SetPropertyValue<string>("historyName", ref _historyName, value);
}
get
{
return _historyName;
}
}
[Association(("HistoryTitles"),typeof (Title))]
public XPCollection Titles { get { return GetCollection("Titles"); } }
public History() : base() {
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}
……
}
public class Title : XPObject
{
string _TitleName;
[Size(50)]
public string TitleName
{
set
{
SetPropertyValue<string>("TitleName", ref _TitleName, value);
}
get
{
return _TitleName;
}
}
string _TitleContent;
public string TitleContent
{
set
{
SetPropertyValue<string>("TitleContent", ref _TitleContent, value);
}
get
{
return _TitleContent;
}
}
[Association("TitleTypes")]
public TitleType titleType;
[Association(("HistoryTitles"), typeof(History))]
public XPCollection Historys { get { return GetCollection("Historys"); } }
public Title() : base() {
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}
…….
}
{
string _historyName;
[Size(50)]
public string historyName
{
set
{
SetPropertyValue<string>("historyName", ref _historyName, value);
}
get
{
return _historyName;
}
}
[Association(("HistoryTitles"),typeof (Title))]
public XPCollection Titles { get { return GetCollection("Titles"); } }
public History() : base() {
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}
……
}
public class Title : XPObject
{
string _TitleName;
[Size(50)]
public string TitleName
{
set
{
SetPropertyValue<string>("TitleName", ref _TitleName, value);
}
get
{
return _TitleName;
}
}
string _TitleContent;
public string TitleContent
{
set
{
SetPropertyValue<string>("TitleContent", ref _TitleContent, value);
}
get
{
return _TitleContent;
}
}
[Association("TitleTypes")]
public TitleType titleType;
[Association(("HistoryTitles"), typeof(History))]
public XPCollection Historys { get { return GetCollection("Historys"); } }
public Title() : base() {
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}
…….
}
实际上, XPO会在你的数据库中除了生成想对应的这2个类以外,它还会额外的增加他们两者之间的一个关联类, 该实例中生成的数据表如下图: