- 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/
我已经设置了我的 EF 代码优先数据库,但想要添加其他派生属性。 (是的,它应该在 View 模型中,我们可以下次再讨论为什么会这样。)我创建了一个扩展实际表类的部分类。如果我将 [NotMapped
我首先使用 EF6 代码,然后我使用了 this答案映射List在我的实体中。 这是我的类(class) [Key] public string SubRubro { get; set
我无法在实体属性上使用 [NotMapped] 属性,因为迁移添加命令在下面抛出错误; 这是我的POCO; using System; using System.Collections.Generic
我正在使用 EF Core 3.0 将数据从 SQL Server 存储过程提取到名为 Recipient 的对象模型中。 Recipient 模型定义了几个属性,EnvelopeId 和 Name,
为什么在下面的示例中需要 [NotMapped] 属性: public virtual ICollection Blogs { get; set; } [NotMapped] public L
我刚刚将 entityframework 更新到最新的 5.0.0 版本。 NotMapped 注释现在不起作用。我试图在谷歌上搜索修复它的答案,但找不到。当您更新 Entity Framework
我有一个运行良好的实体,但我需要添加来自另一个表的附加属性。我没有创建 View 的能力,所以我只想添加一个 [NotMapped] 字段,然后使用 Context.Database.SqlQuery
我有一些模型类用作 Entity Framework 代码优先模型。我在这些模型上有一些不属于数据库模式的属性,为了确保 Entity Framework 不会混淆,我用 [NotMapped] 属性
我正在开发一个 asp.net mvc-5 网络应用程序,我正在使用 Entity Framework 5.0。我映射了创建 .edmx 文件的 SQL 服务器数据库表。现在我想扩展模型类以具有额外的
我是 laravel 的新手,因此我的问题对某些人来说可能很奇怪。好吧,我的问题是如何在 Laravel Model 类中编写一个实体,该实体在迁移后不会在数据库中创建任何字段。例如 class Jo
我在尝试保存更改时收到以下异常:System.Data.SqlClient.SqlException:列名“ClientID”无效。列名称“ID”无效。 ClientID 属性有一个 [NotMapp
我有一个用 context.Database.SqlQuery("MyProc") 执行的存储过程 MyObject有一个只读属性: [NotMapped] public bool IsSomethi
我有一个 WebAPI 后端,它使用 ODATA v3 向各种客户端提供库存信息等(由于我们使用的组件的限制,我不能使用 v4)。库存数据库非常大(超过 10 万条记录),ODATA 非常适合服务器端
有时从这样的基类派生我的实体很有用: public abstract class DestructableBase : IDestructable { /// /// If true,
我将 WCF 数据服务用于返回 JSON 响应的 RESTful API。 考虑这个对象: [Table("person")] public class Person { [Column("d
我有以下类(class): public class Contact { public int ContactID { get; set; } public string FirstN
这是一个有点复杂的问题,请耐心等待。我们目前在我们的服务器上使用 Entity Framework 6.1.1,在客户端使用 OData 5.6 和 Breeze JS 1.5.4。简而言之,我们在将
我已经开始玩 Dapper.Net,到目前为止我真的很喜欢它 - 然而,我遇到了一个问题。 假设我有一个 POCO 类: public class Person { public string
我已经开始玩 Dapper.Net,到目前为止我真的很喜欢它 - 然而,我遇到了一个问题。 假设我有一个 POCO 类: public class Person { public string
我正在尝试弄清楚如何将 NotMapped 属性与 OData 结合使用 我有这个用户模型: [DataContract] public class User { [DataMember] publi
我是一名优秀的程序员,十分优秀!