0

我对 WCF RIA 服务和 Microsoft LightSwitch 的理解已经走了很长一段路,但现在我不知所措。我将使用AnimalDog作为示例。我实际上想要一个零或一对一的关系,并不是每个动物都一定是/有狗。

首先,我在我想与 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中编写一对一或一对一或一对一或零对一的关系灯开关。

实际上,我已经设法使这一切都与一对多的关系一起工作,并且简短而合理的代码看起来“正确”,因此这种变化应该是可以实现的。

4

1 回答 1

1

LightSwitch 实际上并不支持一对一的关系,因此即使您在 RIA 服务中取得了成功,它也不会在 LightSwitch 中起作用。

解决方法是创建具有多重零对多或一对多的关系(正如您最终所做的那样)。您必须在验证或代码中“强制”一对一。

于 2013-04-18T10:12:33.223 回答