1

我有一个要保存的实体的客户端图。当我尝试添加实体时(如下所述),Breeze 报告标题错误。

我能够按需排除/包含实体,因此能够让 Breeze 在图中保留其他所有内容,然后最后尝试添加该实体。错误始终报告。

我在控制器的 saveBundle 中捕获了实体的 JSON 表示,并且能够手动将其插入到数据库中,这让我可以确保它被正确创建。

我不知道如何进一步调试它,并希望得到一些指导。

这是代码优先类(必需:日期时间、值、消息、用户):

public Guid ID { get; set; }

public Guid MessageID { get; set; }
public Guid UserID { get; set; }

public DateTime DateTime { get; private set; }
public float Value { get; set; }

public virtual Message Message { get; set; }
public virtual User User { get; set; }

public virtual ICollection<PropertyValue> PropertyValues { get; set; }

这是保存包:

{
  "entities": [
    {
      "ID": "cdc7a329-1ddc-4535-98f1-fd878af48823",
      "MessageID": "57e88bc1-edc2-4905-af74-09df83edeba5",
      "UserID": "1269a0ad-1019-471c-bdf9-a6e61aea468c",
      "DateTime": "2013-01-04T23:32:01.067Z",
      "Value": 0,
      "entityAspect": {
        "entityTypeName": "Score:#MyProjectName.Repo",
        "entityState": "Added",
        "originalValuesMap": {},
        "autoGeneratedKey": {
          "propertyName": "ID",
          "autoGeneratedKeyType": "Identity"
        }
      }
    }
  ],
  "saveOptions": {
    "allowConcurrentSaves": false
  }
}

这是SQL:

insert into Scores (
    [MessageID],
    [UserID],
    [DateTime],
    [Value]
) values (
    '57e88bc1-edc2-4905-af74-09df83edeba5',
    '1269a0ad-1019-471c-bdf9-a6e61aea468c',
    '2013-01-04T23:28:18.872Z',
    0
)

更新

服务器的事件版本以“System.ArgumentNullException”开头

Value cannot be null.\r\nParameter name: source

和:

at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
at Breeze.WebApi.EFContextProvider`1.SaveChangesCore(Dictionary`2 saveMap)
at Breeze.WebApi.ContextProvider.SaveChanges(JObject saveBundle)
at [MyProject].[MyController].SaveChanges(JObject saveBundle) in ..\Controllers\[MyController].cs:line 53
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4()
at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)
4

2 回答 2

3

我会说您更新的问题中的堆栈跟踪确认异常发生在服务器上。

查看源代码EFContextProvider,您报告的异常似乎是在处理 EF 验证错误(~第 125 行)中抛出EFContextProvider.SaveChangesCoreforeach。它正在准备来自 EF 的有关实体验证错误的消息saveChanges并且失败(意外),因为EntityKeyValues错误实体的密钥没有。那应该是不可能的(哈)!似乎要求 EF 保存没有密钥的实体。

您可以帮助我们诊断如下:

  1. EFContextProvider2在您的模型项目中创建一个新类
  2. EFContextProvider 粘贴来自 GitHub 源代码的副本。
  3. 一定要重命名类EFContextProvider2并使项目编译
  4. EFContextProvider2在您的 Web API 控制器中替换
  5. 在第 124 行设置断点,就在它格式化密钥之前
  6. 在调试器下重现问题

检查key.EntityKeyValues. 我敢打赌,对于违规实体,它们是空的。那是什么实体?错误是eve.ValidationErrors什么?这个特定实体是如何在您的模型中定义的?

当您获得有关错误的更多信息时,我们(嗯,您)会知道更多。

让我们知道您的发现。

1 月 9 日更新

现在我已经看到了一些代码,问题对我来说更加明显。

您的服务器端模型表明 Score.Message 和 Score.User 属性是必需的。好吧,它们不存在于服务器上的 EF 上下文中,因此您无法通过验证。

Score.Message 和 Score.User 是导航属性,分别返回相关的 Message 和 User 对象。

保存时,EF 会尽职尽责地验证这些相关实体是否存在。好吧,他们不是。它们不是因为您(正确地)关闭了延迟加载,这意味着 EF 无法检索它们。

这些实体是否在您的 Breeze 客户端上缓存并不重要。Breeze 不会将它们作为保存包的一部分发送到服务器。

也不应该这样做!您正在保存新乐谱。但是您没有更改分数的相关消息或用户。因此,唯一需要保存的实体是分数。这就是为什么它是您的存档包中唯一且唯一的实体。

EF 正在做你告诉它做的事情:如果没有相关的消息或用户,请尖叫。

我对您的问题是:您为什么需要消息或用户?分数有它们的外键。您是否试图确保这些密钥有效?他们引用数据库中的实际消息和用户行吗?对我来说似乎有点矫枉过正。如果您打开了引用约束,数据库将确保为您服务。如果这些约束已关闭,那么这些验证将在分数插入/更新期间保护您;但他们不会阻止某人独立删除消息或用户......从而孤立分数。

如果您坚持,您可以通过在 BeforeSave... 方法中显式加载这些属性来满足 EF。我会假设你有 EF 印章来做到这一点......否则你可以在网上找到它。

但是,正如我所说,这对我来说似乎有点矫枉过正。

顺便说一句,注释掉 Score 的 Message 和 User 属性上的 [Required] 属性释放了 EF 来保存新的 Score。由于其他原因(console.debug在我的环境中未定义),该应用程序在客户端上爆炸了,但我将把它留给你。

你的模型

你是怎么得到这个模型的。分数看起来像是由某物生成的。我不熟悉 MVC 脚手架,所以请原谅我的无知。但是当我看到它和两个部分类的业务时,我知道它很丑,其中一个包含元数据“伙伴”类……现在这很丑。许多(如果不是大多数)属性都是多余的。

我想不出一个很好的理由来做这一切。一个简单的 POCO-ish 类有什么问题,在正确的属性上装饰有验证属性。这样做,您的模型将更容易理解。

jQuery 延迟是怎么回事?

我意识到它离题了,但我看到你会付出很多努力将Q 承诺变成 jQuery 延迟?那是你的选择。但是你不能用 Q 做的更好或更好的延迟。如果你坚持使用 Q,你可以删掉很多丑陋的代码。只是说。

于 2013-01-05T19:48:00.770 回答
0

我可能完全不在这里,但我认为这是 DateTime 字段。如果您可以尝试将字段更改为可为空的值。

  public DateTime? DateTime { get; private set; }

在 EF 内部的某处,它不将“2013-01-04T23:32:01.067Z”识别为有效格式,因此将其设为空。SQL 确实可以识别它,因此您的插入语句有效。

我通过使用 moment.js 格式化日期来解决这个问题,这样它就会像“1/4/2012 23:32:01”或类似的那样通过电线。

我相信你已经知道了,但是 Z 使它成为 UTC。我在将日期提前 8 小时(我在加州)时遇到了问题。将其格式化为类似格式的文本也可以解决此问题。

于 2013-01-06T02:03:48.283 回答