添加Navigation属性会破坏breeze客户端映射(但不是服务器端EF6)

时间:2015-01-12 16:26:01

标签: entity-framework breeze

我有一个我独立开发的应用程序,现在我正在尝试集成到更大的模型中。目前,在服务器端,每个表有11个表和平均三个导航属性。这是运作良好和稳定。

较大的模型有55个实体和180多个关系,并且包括我的大部分模型(较少与较大模型中的表的关系)。一旦集成,就会发生一件非常奇怪的事情:服务器发送相同的数据,返回相同数量的实体,但exportEntities函数返回一个大约150KB的字符串(而不是之前返回的1.48 MB)并且所有查询都显示他们之前展示的数据的十分之一。

我按照Breeze网站上的疑难解答信息进行操作。我浏览了Breeze元数据,似乎正确定义了实体和关系。我查看了返回的数据,10个实体中有9个没有作为对象出现,但是作为一个函数:function (){return e.refMap[t]}当我展开它时,它有一个'arguments'属性:Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

作为参考,以下是破坏性变化中涉及的两个实体。

还款实体

public class Repayment
{
    [Key, Column(Order = 0)]
    public int DistrictId { get; set; }

    [Key, Column(Order = 1)]
    public int RepaymentId { get; set; }

    public int ClientId { get; set; }

    public int SeasonId { get; set; }

     ...

    #region Navigation Properties

    [InverseProperty("Repayments")]
    [ForeignKey("DistrictId")]
    public virtual District District { get; set; }


    // The three lines below are the lines I added to break the results
    //  If I remove them again, the results are correct again
    [InverseProperty("Repayments")]
    [ForeignKey("DistrictId,ClientId")]
    public virtual Client Client { get; set; }

    [InverseProperty("Repayments")]
    [ForeignKey("DistrictId,SeasonId,ClientId")]
    public virtual SeasonClient SeasonClient { get; set; }

客户实体

public class Client : IClient
{
    [Key, Column(Order = 0)]
    public int DistrictId { get; set; }

    [Key, Column(Order = 1)]
    public int ClientId { get; set; }

    ....

    // This Line lines were in the original (working) model
    [InverseProperty("Client")]
    public virtual ICollection<Repayment> Repayments { get; set; }

    ....
}

我恢复的关系只是已经存在的关系的逆转,这是关于它的一个非常奇怪的事情。我确信我做的事情非常糟糕,但我现在还不确定哪些信息可能对调试这个有所帮助。

为了定义外键和反向属性,我假设我必须使用数据注释或FluentAPI,即使表遵循所有EF约定。要么一个比另一个好?是否有必要始终如一地选择一种方法并坚持下去?以上错误是否提供了我可能做错的任何见解?我可以发布任何其他可能有用的信息吗?

Breeze是一个优秀的框架,有可能真正扩大我们的范围,为东非农村地区的小农提供援助,我很乐意让这个原型工作。

感谢

2 个答案:

答案 0 :(得分:1)

好的,您所描述的一些内容可以通过breeze的压缩任何返回同一实体的多个实例的查询结果的有效负载的默认行为来解释。如果您使用类似默认的'json.net'程序集进行序列化,那么每个实体都会发送一个额外的'$ id'属性,如果再次看到同一个实体,它将通过简单的'$ ref'属性进行序列化前面提到的'$ id'的值。

在反序列化期间的breeze客户端上,这些'$ refs'被解析回完整的实体。但是,由于执行反序列化的顺序可能与序列化可能执行的顺序不同,因此breeze在内部创建延迟闭包函数(不带参数),允许延迟解析压缩结果,而不管顺序如何序列化。这是

function (){return e.refMap[t]}
你正在看到的。

如果您将此值视为实际顶级查询结果的一部分,那么我们有一个错误,但是如果您在调试从服务器返回的结果时看到此值,则在它们返回到调用函数之前,那么这是完全可取的(特别是如果你在执行之前查看闭包的内容。)

所以有几个问题和建议

  • 您实际上是在查看处理查询结果的错误,还是对结果如此之小感到惊讶?如果这只是一个大小问题,请检查并查看是否可以识别应该已发送到客户端但缺少的数据。在您的情况下,参考压缩可能非常有效。

  • 查看从您的网络服务返回的“原始”数据。看起来应该是这样的,带有'$ id'和'$ ref'属性。

    [{
      '$id': '1',
      'Name': 'James',
      'BirthDate': '1983-03-08T00:00Z',
     },
     {
      '$ref': '1'
    }]
    

    如果是这样,那么查看数据并确保存在与每个'$ refs'对应的'$'id'。如果没有,服务器端序列化代码出现问题。如果数据看起来不像这样,那么请回帖一下“原始”数据的样子。

答案 1 :(得分:0)

在看完你的要点之后,我想我看到了这个问题。您的元数据与查询返回的实际结果不同步。特别是,如果你寻找&#39; $ id&#39;值&#34; 17&#34;在您的实际结果中,您会注意到它首先出现在&#39;客户端&#39; &#39;还款的财产&#39;输入,但您的元数据没有&#39;客户端&#39;为“还款”定义的导航属性类型(有一个&#39; ClientId&#39;)。我的猜测是你正在重复使用年龄较大的&#39;元数据的版本。

这导致结果不完整的原因是,一旦微风确定它正在反序列化一个&#39;实体&#39; (即,具有映射到实际entityType的$ type属性的json对象),它只尝试反序列化已知的&#39;此类型的属性,即元数据中的属性。在您的情况下,&#39;客户&#39;导航财产上的“还款”#39;类型从未被反序列化,并且任何引用都是&#39; $ id&#39;因此没有定义。