我有一个我正在尝试保存的实体的客户端图表。当我尝试添加添加实体(如下所述)时,Breeze会报告标题的错误。
我能够按需排除/包含实体,因此能够让Breeze持久保存图表中的所有其他内容,然后最后尝试添加此实体。报告错误一致。
我在控制器的saveBundle中捕获了实体的JSON表示,并且能够手动将其插入到数据库中,这使我可以确保它正确创建。
我对如何进一步调试感到困惑,并希望得到一些指导。
这是代码优先的类(requireds:DateTime,value,Message,User):
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; }
这是saveBundle:
{
"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)
答案 0 :(得分:3)
我说你更新的问题中的堆栈跟踪确认服务器上发生了异常。
查看EFContextProvider
的来源,您处理EF验证错误的EFContextProvider.SaveChangesCore
内的foreach
似乎会引发您报告的异常(〜第125行)。它正在准备一条关于来自EF saveChanges
的实体验证错误的消息,并且(意外地)失败,因为错误实体的密钥没有EntityKeyValues
。那不可能(哈)!似乎EF被要求保存没有密钥的实体。
您可以帮我们诊断如下:
EFContextProvider2
类EFContextProvider
from GitHub source 的副本。EFContextProvider2
并使项目编译EFContextProvider2
检查key.EntityKeyValues
。我打赌他们对违规实体来说是空的。那个实体是什么?错误是什么eve.ValidationErrors
?如何在您的模型中定义此特定实体?
当您获得有关错误的更多信息时,我们(嗯,您)将会了解更多信息。
让我们知道你发现了什么。
现在我已经看到了一些代码,问题对我来说更明显。
您的服务器端模型表示需要Score.Message和Score.User属性。好吧,它们不会出现在服务器上的EF上下文中,因此您无法通过验证。
Score.Message和Score.User是导航属性,分别返回相关的Message和User对象。
保存时,EF会尽职尽责地确认这些相关实体存在。好吧,他们不是。它们并不是因为你(正确地)关闭了延迟加载,这意味着EF无法检索它们。
根本不重要的是这些实体是否在Breeze客户端的缓存中。 Breeze不会将它们作为保存包的一部分发送到服务器。
也不应该这样做!您正在保存新的分数。但是你并没有改变乐谱相关的消息或用户。因此,唯一需要保存的实体是分数。这就是为什么它是保存包中唯一的实体。
EF正在按照你的要求去做:如果没有相关的消息或用户就会尖叫。
我的问题是:你为什么要求留言或用户?得分有他们的外键。您是否尝试确保这些密钥有效?他们引用数据库中的实际Message和User行?对我而言似乎有点矫枉过正。如果您启用了参照约束,数据库将确保为您服务。如果这些约束关闭,那么这些验证将在分数插入/更新期间保护您;但他们不会阻止某人独立删除消息或用户......从而使分数孤立。
如果你坚持,你可以通过在BeforeSave ...方法中显式加载这些属性来满足EF。我假设你有EF印章来做到这一点......否则你可以在网上找到它。
但是,正如我所说,这对我来说似乎有点过分了。
BTW,在乐谱的消息和用户属性上注释掉[必需]属性,释放EF以保存新分数。由于其他原因(console.debug
在我的环境中未定义),该应用程序在客户端上爆炸了,但我会留给您。
你是如何得到这个模型的。分数看起来像是由某些东西产生的。我不熟悉MVC脚手架,所以请原谅我的无知。但是,当我看到它并且两个部分类的业务时,我知道丑陋,其中一个包含元数据&#34; buddy&#34;上课...现在这很丑陋。许多(如果不是大多数)属性都是多余的。
我无法想到所有这一切的充分理由。单个简单的POCO-ish类有什么问题,在适当的属性上装饰了验证属性。这样做,您的模型将更容易理解。
我意识到它的主题但是我看到你需要付出很多努力才能将Q promises变成jQuery延迟?这是你的选择。但是对于延迟而言你无能为力,你可以用Q做得更好或更好。如果你坚持使用Q,你可以删除许多丑陋的代码。只是说。
答案 1 :(得分:0)
我可能完全不在这里,但我认为这是DateTime字段。如果您可以尝试将字段更改为可以为空的值。
public DateTime? DateTime { get; private set; }
在EF内部的某处,它不会将“2013-01-04T23:32:01.067Z”识别为有效格式,因此它将其置零。 SQL确实识别它,因此您的insert语句有效。
我通过使用moment.js格式化日期解决了这个问题,因此它以“1/4/2012 23:32:01”或其他类似的方式进入了网络。
我相信你已经知道,但Z使它成为UTC。我有一个问题,提前8小时(我在加州)。将其格式化为文本格式也可以解决这个问题。