- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是一个有点复杂的问题,请耐心等待。我们目前在我们的服务器上使用 Entity Framework 6.1.1,在客户端使用 OData 5.6 和 Breeze JS 1.5.4。简而言之,我们在将模型上的 [NotMapped] 属性序列化为 json 并传递给客户端时遇到了问题。
这是我们的模型:
public class Request
{
...
public int UserId { get; set; }
[NotMapped]
public string UserName {get; set; }
}
因为我们使用的是 OData,而不是通过默认的 JsonMediaTypeFormatter
进行序列化,它通过 OdataMediaTypeFormatter
完全忽略 [NotMapped] 的任何内容
属性。我们可以通过手动将属性添加到 modelBuilder
来解决这个问题。然而,当尝试与 Breeze 集成时,这会成为一个问题,因为它们有自己的自定义 EdmBuilder,必须用于保存可导航属性等内容,而我们不能使用标准的 ODataConventionModelBuilder
。这个自定义构建器似乎不允许对模型进行任何级别的控制。是否有可能强制 OData 正确序列化这些属性并保留与 Breeze 不符的元数据?以前有人尝试过类似的东西吗?
边注:我们试图避免在数据库中为这些数据存储或只是创建虚拟列,因为我们需要其中的 5 个属性,但如果我们在这方面投入太多时间,这可能最终会成为我们的行动方针。
提前致谢
最佳答案
在序列化方面,伤害你的是breeze提供的中间EdmBuilder。请参阅:https://github.com/Breeze/breeze.server.labs/blob/master/EdmBuilder.cs
由于EdmBuilder.cs的注释定义的限制
We need the EDM both to define the Web API OData route and as a source of metadata for the Breeze client. The Web API OData literature recommends the System.Web.Http.OData.Builder.ODataConventionModelBuilder.That component is suffient for route definition but fails as a source of metadata for Breeze because (as of this writing) it neglects to include the foreign key definitions Breeze requires to maintain navigation properties of client-side JavaScript entities.This EDM Builder ask the EF DbContext to supply the metadata which satisfy both route definition and Breeze.You're only getting the metadata the EntityFramework chooses to expose. This prevents the OData formatters/serializers from including the property - it's not mapped in the model metadata.
You could attempt a solution with a custom serializer, similar to what is represented in this article. Using OData in webapi for properties known only at runtime
A custom serializer would look roughly like this (Note: this DOES NOT work.. continue reading, below...)
public class CustomEntitySerializer : ODataEntityTypeSerializer
{
public CustomEntitySerializer(ODataSerializerProvider serializerProvider) : base(serializerProvider) { }
public override ODataEntry CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
{
ODataEntry entry = base.CreateEntry(selectExpandNode, entityInstanceContext);
Request item = entityInstanceContext.EntityInstance as Request;
if (entry != null && item != null)
{
// add your "NotMapped" property here.
entry.Properties = new List<ODataProperty>(entry.Properties) { new ODataProperty { Name = "UserName", Value = item.UserName} };
}
return entry;
}
}
问题在于底层 ODataJsonLightPropertySerializer 在尝试写入时会检查模型是否存在该属性。它调用 Microsoft.Data.OData.WriterValidationUtils 类中的 ValidatePropertyDefined 方法。
internal static IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType)
这将使您因运行时异常而失败:
The property 'UserName' does not exist on type 'YourNamespace.Models.Request'. Make sure to only use property names that are defined by the type.","type":"Microsoft.Data.OData.ODataException","stacktrace":" at Microsoft.Data.OData.WriterValidationUtils.ValidatePropertyDefined(String propertyName, IEdmStructuredType owningStructuredType)\r\n at Microsoft.Data.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperty(ODataProperty property, IEdmStructuredType owningType, Boolean isTopLevel, Boolean allowStreamProperty, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties
Bottom line is that the property needs to be defined in the model in order to serialize it. You could conceivably rewrite large portions of the serialization layer, but there are lots of internal/static/private/non-virtual bits in the OData framework that make that unpleasant.
A solution is ultimately presented in the way Breeze is forcing you to generate the model, though. Assuming a code-first implementation, you can inject additional model metadata directly into the XmlDocument produced by EntityFramework. Take the method in the Breeze EdmBuilder, with some slight modifications:
static IEdmModel GetCodeFirstEdm<T>(this T dbContext) where T : DbContext
{
// create the XmlDoc from the EF metadata
XmlDocument metadataDocument = new XmlDocument();
using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream))
{
System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(dbContext, writer);
stream.Position = 0;
metadataDocument.Load(stream);
}
// to support proper xpath queries
var nsm = new XmlNamespaceManager(metadataDocument.NameTable);
nsm.AddNamespace("ssdl", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");
nsm.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2009/11/edmx");
nsm.AddNamespace("edm", "http://schemas.microsoft.com/ado/2009/11/edm");
// find the node we want to work with & add the 1..N property metadata
var typeElement = metadataDocument.SelectSingleNode("//edmx:Edmx/edmx:Runtime/edmx:ConceptualModels/edm:Schema/edm:EntityType[@Name=\"Request\"]", nsm);
// effectively, we want to insert this.
// <Property Name="UserName" Type="String" MaxLength="1000" FixedLength="false" Unicode="true" Nullable="true" />
var propElement = metadataDocument.CreateElement(null, "Property", "http://schemas.microsoft.com/ado/2009/11/edm");
propElement.SetAttribute("Name", "UserName");
propElement.SetAttribute("Type", "String");
propElement.SetAttribute("FixedLength", "false");
propElement.SetAttribute("Unicode", "true");
propElement.SetAttribute("Nullable", "true");
// append the node to the type element
typeElement.AppendChild(propElement);
// now we're going to save the updated xml doc and parse it.
using (var stream = new MemoryStream())
{
metadataDocument.Save(stream);
stream.Position = 0;
using (var reader = XmlReader.Create(stream))
{
return EdmxReader.Parse(reader);
}
}
}
这会将属性放入元数据中以供 OData 层使用,并且不需要任何额外的步骤来促进序列化。但是,您需要注意如何塑造模型元数据,因为任何要求/规范都将反射(reflect)在 Breeze 的客户端验证中。
我已经在 Breeze 提供的 ODataBreezejs 示例中验证了这种方法的 CRUD 操作。 https://github.com/Breeze/breeze.js.samples/tree/master/net/ODataBreezejsSample
关于c# - 尝试序列化 [NotMapped] Entity Framework 属性以供 Breeze 使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32105349/
我正在考虑使用 Breeze js,并对其功能和随之而来的最佳实践有一些疑问。 服务器端元数据是否必须存在?如果我有一个非 EF WebApi Controller ,我是否仍然需要用 Provide
我们正在考虑使用breeze js来构建企业应用程序。 轻而易举的是,我们可以直接从客户端浏览器执行查询。这允许基于用户输入构造动态查询,而无需加载不必要的数据。我发现使用Breeze可以创建业务逻辑
我有一个从另一个表继承的表。当我运行该项目时,出现以下错误:无法获取未定义或空引用的属性“propertyref”...有什么想法吗? 最佳答案 编辑:从 v 1.3.1 Breeze 开始,现在支持
想知道是否有人知道扩展或配置 Breeze 以便服务器返回实体元数据中的附加信息的任何方法?我想使用这些附加数据来协助验证。 假设我有一个应用了一些数据注释的实体模型: public class Pe
我使用 Durandal/breeze 开发了一个 asp.net 解决方案。 这是我获取所有托运人的代码: var query = EntityQuery.from('Shippers')
我已经阅读了 Breeze 验证器信息,但不确定如何查看正在发生的实际错误。 错误:遇到客户端验证错误 - 有关更多详细信息,请参阅此对象上的实体错误集合。 我相信它在 entity.entityAs
我正在使用 Breeze 过滤客户端请求的数据。我的代码看起来有点像这样: 客户端 - 创建过滤谓词 var predicates = []; var criteriaPredicate = null
我在处理日期时遇到了一些问题。 我有一个带有日期字段的对象: public DateTime FechaInicio{get;设置; 此定义在数据库中生成以下字段: FechaInicio 日期时间不
我在处理日期时遇到了一些问题。 我有一个带有日期字段的对象: public DateTime FechaInicio{get;设置; 此定义在数据库中生成以下字段: FechaInicio 日期时间不
如果我使用微风加载部分实体: var query = EntityQuery.from('material') .select('Id, MaterialName, Mater
改进我关于如何使用获得的元数据在淘汰赛中创建验证规则的示例(http://stackoverflow.com/questions/13662446/knockout-validation-using-
我想更改 Breeze 的序列化程序,以便我的 javascript 对象是驼峰式的。在文档中它说这是可以做到的,但说这是有待解释的。 You can change the formatter's c
给定一个具有导航属性的实体,有没有办法判断空导航属性是否是因为子实体从未被加载,而不是集合已经加载但只是空的? 例如:我加载一个包含实体 A 列表的页面。每个实体 A 都有一个导航属性,它是实体 B
我使用 Entity Framework Code First + Durandal + Breeze 开发一个项目。 我有这些实体模型: public class Packing { [Ke
我正在尝试使用 breeze.js 保存一些实体。 Breeze 工作正常,它会根据需要保存所有更改。但是,我无法验证并确保授权是服务器端的。从我目前收集到的信息来看,我猜想做到这一点的唯一方法是检查
我们有一个轻而易举的客户解决方案,其中向父实体显示其子列表。我们对某些子实体进行硬删除。现在,当用户是执行删除操作的用户时,没有问题,但是当其他用户执行操作时,似乎没有办法使已经加载到缓存中的子项失效
我想用 Breeze.js 搜索文本 var qu = new breeze.EntityQuery("Projects") .where("Name", "s
从表面上看,这可能听起来像一个愚蠢的问题,但为什么 Hot Towel SPA Template包括 Breeze根本? 最近几天我一直在学习 Hot Towel 及其依赖项,据我所知,模板中没有任何
假设我想使用 Breeze 创建一个任务实体(我正在使用 EF),但是因为这是一个真实任务应用程序,所以该任务必须关联到当前登录的用户.任务具有需要在保存期间填充的 UserId 外键,这就是我遇到的
我正在尝试根据子实体的集合来过滤实体。这是我的实体(EF POCO): public class Customer { public int Id { get; set; } publ
我是一名优秀的程序员,十分优秀!