我对 WCF RIA 服务和 Microsoft LightSwitch 的理解已经走了很长一段路,但现在我不知所措。我将使用Animal
和Dog
作为示例。我实际上想要一个零或一对一的关系,并不是每个动物都一定是/有狗。
首先,我在我想与 RIA 服务一起使用的数据库中创建一个一对一的关系。然后像往常一样更新我的 RIA 服务项目中的 Model.edmx 文件。问题不是这让我可以ObjectContext.Dogs
像我期望的那样访问,它不存在,而是 Animal 被赋予了 Dog 的额外属性。显然,一对一的关系是以这种方式特别处理的,这似乎是有帮助的,但我很难以这种方式处理它。
我的 RIA 服务类如下所示:
public class RiaDog
{
[Key]
public int Id { get; set; }
public int PackLeaderId { get; set; }
[Association("RiaAnimal_RiaDog", "Id", "Id", IsForeignKey = true)]
public RiaAnimal Animal { get; set; }
}
public class RiaAnimal
{
[Key]
public int Id { get; set; }
[Association("RiaAnimal_RiaDog", "Id", "Id", IsForeignKey = false)]
public RiaDog Dog { get; set; }
}
除非有某种我不知道的神奇的一对一数据注释属性,否则我必须为每个其他类RiaDog
编写CRUD 方法。RiaAnimal
鉴于 ObjectContext.Dogs 不存在这一事实,这变得非常尴尬,我必须通过 Animal 工作:
[Query(IsDefault = true)]
public IQueryable<RiaDog> GetAllDogs() {
var report = from animal in ObjectContext.Animals
where animal.PackLeader != null
select new RiaDog
{
Id = animal.Id,
PackLeaderId = animal.Dog.PackLeaderId,
};
return report;
}
这已经感觉很奇怪了,我必须在 Dog 属性之一上使用 where 子句来隔离狗。
通过一些简单的创意,我可以获得插入、更新和删除方法的功能:
public void InsertDog(RiaDog riaDog) {
var animal = ObjectContext.Animals.FirstOrDefault(a => a.Id == riaDog.Id);
animal.PackLeader = ObjectContext.PackLeaders.FirstOrDefault(pl => pl.Id == riaDog.PackLeaderId);
riaDog.Animal.Dog = riaDog;
}
public void UpdateDog(RiaDog rd) {
var animal = ObjectContext.Animals.FirstOrDefault(a => a.Id == riaDog.Id);
animal.PackLeader = ObjectContext.PackLeaders.FirstOrDefault(pl => pl.Id == riaDog.PackLeaderId);
}
public void DeleteDog(RiaDog rd) {
}
在UpdateAnimal()
我使用我设置的反向引用InsertDog()
并添加:
if (riaAnimal.Dog == null)
riaAnimal.PackLeader = null;
我也将 Dog 设置为与数据库上的 Animal 级联删除。
在 LightSwitch 前端,我在 RiaDog 实体上有这个:
partial void AnimalType_Changed() {
if (AnimalType != null && AnimalType.Name == "Dog" && this.Dog == null)
this.Dog == new RiaDog();
else if (this.Dog != null && (AnimalType == null || AnimalType.Name != "Dog"))
this.Dog = null;
}
我遇到的问题是,如果我将类型更改为 Dog,保存,将其更改回其他内容,保存,然后再次将其更改为 Dog 并保存,我会收到错误消息:The context is already tracking a different entity with the same resource Uri.
我学会了处理其他跟踪错误:
在代码隐藏客户端中创建实体时,它们需要唯一的 ID 才能在客户端正确跟踪。
在 WCF RIA Services 中的任何插入方法中,实体的客户端 ID 必须在数据库生成后设置为真实 ID,例如:
public void InsertRiaEntity(RiaEntity re) {
var entity = new Entity();
entity.SomeProperty = re.SomeProperty;
entity.AnotherProperty = re.AnotherProperty;
ObjectContext.Entities.AddObject(entity);
ObjectContext.SaveChanges();
// essential for client<->server tracking
re.Id = entity.Id;
}
但是我不知道如何解决这个当前的跟踪错误。真的,我觉得我采取了错误的方法,我正在寻找专家的建议,了解您应该如何在 WCF RIA Services for Microsoft中编写一对一或一对一或一对一或零对一的关系灯开关。
实际上,我已经设法使这一切都与一对多的关系一起工作,并且简短而合理的代码看起来“正确”,因此这种变化应该是可以实现的。