http://www.rainsts.net/article.asp?id=242
在ActiveRecord中级联操作为我们带来很多方便,但是一些细节地方需要注意。
[ActiveRecord("Users")]
public class User : ActiveRecordBase
{
public User()
{
}
public User(string name) : this()
{
this.name = name;
}
private int id;
[PrimaryKey(PrimaryKeyType.Identity)]
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
[Property(Unique=true)]
public string Name
{
get { return name; }
set { name = value; }
}
private Company company;
[BelongsTo("CompanyId")]
public Company Company
{
get { return company; }
set { company = value; }
}
}
[ActiveRecord("company")]
public class Company : ActiveRecordBase
{
public Company()
{
}
public Company(string name) : this()
{
this.name = name;
}
private int id;
[PrimaryKey(PrimaryKeyType.Identity)]
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
[Property(NotNull=true)]
public string Name
{
get { return name; }
set { name = value; }
}
private IList users = new ArrayList();
[HasMany(typeof(User), ColumnKey = "CompanyId", Table = "Users", Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList Users
{
get { return users; }
set { users = value; }
}
public static Company Find(int id)
{
return FindByPrimaryKey(typeof(Company), id) as Company;
}
}
public class User : ActiveRecordBase
{
public User()
{
}
public User(string name) : this()
{
this.name = name;
}
private int id;
[PrimaryKey(PrimaryKeyType.Identity)]
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
[Property(Unique=true)]
public string Name
{
get { return name; }
set { name = value; }
}
private Company company;
[BelongsTo("CompanyId")]
public Company Company
{
get { return company; }
set { company = value; }
}
}
[ActiveRecord("company")]
public class Company : ActiveRecordBase
{
public Company()
{
}
public Company(string name) : this()
{
this.name = name;
}
private int id;
[PrimaryKey(PrimaryKeyType.Identity)]
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
[Property(NotNull=true)]
public string Name
{
get { return name; }
set { name = value; }
}
private IList users = new ArrayList();
[HasMany(typeof(User), ColumnKey = "CompanyId", Table = "Users", Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList Users
{
get { return users; }
set { users = value; }
}
public static Company Find(int id)
{
return FindByPrimaryKey(typeof(Company), id) as Company;
}
}
在上面的代码中我们为 Company.Users 添加了级联操作属性。接下来我们分别验证一下在级联(Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)和非级联(Cascade=ManyRelationCascadeEnum.None)方式下操作对象有什么不同。。
1. 级联方式插入:创建Company和其关联的用户,company.Create() 会自动保存company.Users中的关联对象。
using (TransactionScope trans = new TransactionScope())
{
try
{
Company company = new Company("公司A");
for (int i = 1; i <= 10; i++)
{
User user = new User("用户" + i);
company.Users.Add(user);
}
company.Create();
trans.VoteCommit();
}
catch
{
trans.VoteRollBack();
}
}
{
try
{
Company company = new Company("公司A");
for (int i = 1; i <= 10; i++)
{
User user = new User("用户" + i);
company.Users.Add(user);
}
company.Create();
trans.VoteCommit();
}
catch
{
trans.VoteRollBack();
}
}
2. 级联方式删除:删除Company对象时,其关联的User对象也正常被删除。
Company company = Company.Find(1);
company.Delete();
company.Delete();
3. 级联方式删除:可以通过移除 Company.User 集合中的 User 对象的方式来删除 User 对象。
Company company = Company.Find(1);
company.Users.RemoveAt(2);
company.Update();
company.Users.RemoveAt(2);
company.Update();
4. 非级联方式插入:必须先创建(保存)Company对象,而且需要指定 User.Company 属性才能正确创建所有对象。
using (TransactionScope trans = new TransactionScope())
{
try
{
Company company = new Company("公司A");
company.Create();
for (int i = 1; i <= 10; i++)
{
User user = new User("用户" + i);
user.Company = company;
user.Save();
}
trans.VoteCommit();
}
catch
{
trans.VoteRollBack();
}
}
{
try
{
Company company = new Company("公司A");
company.Create();
for (int i = 1; i <= 10; i++)
{
User user = new User("用户" + i);
user.Company = company;
user.Save();
}
trans.VoteCommit();
}
catch
{
trans.VoteRollBack();
}
}
5. 非级联方式删除:仅删除了Company对象自身,与之关联的User对象并未被删除,仅将其CompanyId字段设为NULL。
Company company = Company.Find(1);
company.Delete();
company.Delete();
6. 非级联方式删除:移除集合中子对象时,也并未真正将其删除,同样只是将其CompanyId字段设为NULL而已。
Company company = Company.Find(1);
company.Users.RemoveAt(2);
company.Update();
company.Users.RemoveAt(2);
company.Update();
正确的做法
(company.Users[2] as User).Delete();
可见两种方式操作上有很大差异,编码时一定要注意,否则数据库中恐怕会留下许多“僵尸”数据。
------------------
在ManyToMany情况下,非级联删除时,仅会删除自身和映射表中的记录;级联删除会试图删除关联记录。