使用带有nhibernate的ria服务时,无法更新一对多关系

时间:2010-10-05 00:16:11

标签: silverlight nhibernate ria

我正在开发一个silverlight应用程序,我正在使用RIA数据服务和nHibernate。

目前,我有一个与另一个实体有一对多关系的实体。

public class Employer {
    [Key]
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

public class Person {
    [Key]
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    [Include]
    [Association("PersonCurrentEmployer", "CurrentEmployerId", "Id", IsForeignKey = true)]
    public virtual Employer CurrentEmployer { get; set; }
    public virtual int? CurrentEmployerId { get; set; }
}

属性CurrentEmployerId设置为不在映射中进行插入和更新。

在Silverlight方面,我将此人的CurrentEmployer属性设置为客户端的现有雇主提交更改。

personEntity.CurrentEmployer = megaEmployer;
dataContext.SubmitChanges();

在服务器端,人员实体的CurrentEmployerId设置为megaEmployer.Id,但CurrentEmployernull。因为我使用CurrentEmployer属性而不是CurrentEmployerId来保存关系,所以关系不会改变。

有没有办法强制RIA通过保存发送CurrentEmployer对象,或者是否必须使用服务器端的CurrentEmployerId来加载雇主并将其设置为{{1 }}?

3 个答案:

答案 0 :(得分:1)

  

有没有办法强制RIA使用save发送CurrentEmployer对象,还是必须使用服务器端的CurrentEmployerId加载雇主并将其设置为CurrentEmployer?

我也遇到了这个问题。基本上,您要么必须使用[Composition]属性(我不推荐),要么从服务器端的数据库加载实体。组合混淆了客户端数据模型,并没有处理您需要担心的所有情况。 (在RIA forums.silverlight.net上有很多关于作文的内容)

[更新]一旦实现二级缓存,从数据库中读取支持实体的担心大多消失,因为它们将从缓存中加载。此外,如果您只需要NHibernate的代理不要抱怨,那么请查看Get / Load(永远不会记住哪个)..这将返回一个NH代理并将导致从数据库中选择单列和实体。 (如果你试图访问代理的另一个属性,NH将选择其余的属性。你可以在Ayende的博客上找到更多相关内容..)[/ UPDATE]

我遇到的最大问题是让NHib实际保存并加载关系。 (我也在使用Fluent)。到目前为止,责任方的反应是“哇哇,你不能这样做。看起来RIA并不是用NHib开发的”......这是一个垃圾回答,恕我直言。他们没有帮我弄清楚如何映射它,而是告诉我在我的实体中有一个ForeignKey我做错了(NHib不应该关心我的实体中有我的FK)......

答案 1 :(得分:1)

您在客户端没有看到CurrentEmployer的原因是您没有正确设置关联。

RIA服务不能以常规方式使用引用,因此在客户端引用您的雇主不起作用。 RIA服务与实体集一起使用,并根据关联属性创建“引用”。您的雇主需要一个与该人有关联的财产,如下所示。

    public class Employer 
    {
        private Person person;

        [Key]
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual int PersonID { get; set; }

        [Include]
        [Association("PersonCurrentEmployer", "PersonID", "Id", IsForeignKey = false)]
        public virtual Person Person    {
            get
            {
                return this.person;
            }

            set
            {
                this.person = value;
                if (value != null)
                {
                    this.PersonID = value.Id;
                }
            }
        }
    }

答案 2 :(得分:0)

我想分享我为完成这项工作所做的工作,因为对这种情况的'官方'支持是......让我们说充其量只是无益,而且最糟糕的是粗暴无礼。

顺便说一下,你有同样的想法:使外键不插入/更新。但是,我也做了Generated.Always()。这样它总会读回值。

此外,我重写了DomainService.Submit()和DomainService.ExecuteChangeSet()。我在提交中启动了一个NHibernate事务(虽然我还不确定这是否符合我的预期)。

我没有将我的保存逻辑放在InsertSomeEntity()或UpdateSomeEntity()方法中,而是在ExecuteChangeSet中完成所有操作。这是因为NHibernate,它需要在NHibernate中执行动作之前使实体图完全双向并且水合。这包括当子项目来自RIA服务时从数据库或会话加载实体。 (我开始编写方法的路径,以获取图形的各种其他部分,因为那些专门的方法需要它们,但我发现在一个方法中更容易完成所有这些。而且,我遇到了RIA想要的问题我首先对子对象执行插入/更新,这对于新项目是个问题。)

我想对composition属性发表评论。我仍然支持我之前的评论,即不建议将其用于标准子实体集合,但是,它对于支持NHibernate组件非常有用,因为否则RIA将永远不会发回NHibernate工作所需的父组件(组合)。右。

我在这里没有提供任何代码,因为我必须做一些重编,但如果你想看到它,那对我来说不是问题。