我在visual studio 2012中使用Angular / Breeze SPA模板。我在TodoList服务器模型中添加了一个未映射的属性。
[NotMapped]
public string MyUnmappedProperty{ get{return "testString";}}
我在客户端模型的构造函数中注册了未映射的属性,特别是在Ward建议的todo.model.js中:Handling calculated properties with breezejs and web api
function TodoList() {
this.title = "My todos"; // defaults
this.userId = "to be replaced";
this.myUnmappedProperty="";
}
第一次在todo.controller.js上调用getTodos()方法时,“myUnmappedProperty”具有构造函数中设置的空字符串的值。只有在第二次调用getTodos()之后(我添加了一个执行该操作的按钮)并将'forceRefresh'设置为true(getTodos(true))才能查询服务器,只有这样才能看到myUnmappedProperty获取值“的TestString”。
我想知道为什么我会得到这种行为。是否可以在第一次调用getTodos()时使未映射的属性填充服务器值?
谢谢。
答案 0 :(得分:2)
您找到了解决此问题的方法吗?我一直在努力解决同样的问题,最近才发现了CassidyK的this SO post,他在Breeze源代码(breeze.debug.js)中改变了一行来解决一个非常类似的问题。这是他改变的代码片段(取自CassidyK的帖子):
proto.initializeFrom = function (rawEntity) {
// HACK:
// copy unmapped properties from newly created client entity to the rawEntity.
// This is so that we don't lose them when we update from the rawEntity to the target.
// Something that will occur immediately after this method completes.
var that = this;
this.entityType.unmappedProperties.forEach(function(prop) {
var propName = prop.name;
that[propName] = rawEntity[propName]; // CassidyK
//rawEntity[propName] = that[propName]; // Breeze
});
if (!this._backingStore) {
this._backingStore = { };
}
};
我尝试过这个解决方案,似乎工作正常。请注意,如果您遇到的情况是您的服务器端属性未映射到数据库中,并且在客户端创建对象时需要客户端覆盖此值,则此更改可能会让您遇到麻烦。
答案 1 :(得分:1)
读者的一些背景知识。
区分
非常重要 [NotMapped]
是一个EF属性,告诉EF“此属性未映射到数据库”。
[JsonIgnore]
是一个Json.Net属性,它告诉JSON.Net“在将该属性发送到客户端时不会序列化此属性”
只有元数据可以告诉Breeze从哪个角度“映射”...
Breeze通常会忽略元数据中定义的传入属性。但是,如果构造函数中定义了非元数据属性,Breeze会将其添加到元数据并将其分类为“未映射”。
对于Breeze,这意味着“序列化此属性,在更改时通知UI,但这不是实体数据模型的一部分,不应进行更改跟踪(即,对其进行更改不会影响EntityState) )。“
让我们将这些想法放在一起以理解您的问题。
你告诉EF不要映射MyUnmappedProperty
属性。您可能正在使用EFContextProvider
生成元数据,以便属性也不在元数据中。
但是Json.Net并不知道这些。因此,无论何时序列化TodoList
的实例,它都会将MyUnmappedProperty
属性(“testString”)发送给Breeze客户端。
起初Breeze不会对它做任何事情。如果服务器使用任何值发送此属性,Breeze将忽略它。
但是您将MyUnmappedProperty
属性添加到TodoList
类型构造函数中,因此现在Breeze会将此属性识别为“unmapped”,并且如果它出现在JSON查询结果中,它将实现其值。
当您创建TodoList
的新实例(new
或entityManager.CreateEntity(...)
)时,MyUnmappedProperty
属性设置为每个ctor ''
。< / p>
当您查询TodoList
时,Json.NET会在JSON结果中发送{MyUnmappedProperty: "testString}
。 Breeze客户端识别MyUnmappedProperty
,并相应地在物化TodoList
实体实例上设置该属性。
这就是应该发生的事情。
您是否可以证明查询的TodoList
是否已实现,以使其MyUnmappedProperty
不是“testString”?
您已检查过网络流量,但您发现{MyUnmappedProperty: "testString}
实际上是通过网络传输但未实现?你说它是在第二个查询中实现的吗?
我需要一个责备!
答案 2 :(得分:0)
@Ward,谢谢你的回答。
首先,我忘了提到我使用的是Breeze 1.4.0版。
您已经检查了网络流量,并且您看到{MyUnmappedProperty:“testString}实际上正在通过网络:是的我已经检查过它并且包含在来自服务器的JSON发送中
spa模板需要3个小的附加内容才能获得我遇到的行为。
在todo.view.html
我添加按钮“myGetBtn”和带有角度绑定的范围“mySpan”:
...
<button data-ng-click="addTodoList()">Add Todo list</button>
<br/>
<p>
<button id="myGetBtn" ng-click="getTodos(true)">Get todos</button>
</p>
<article class="todoList" data-ng-repeat="list in todoLists">
<header>
<form data-ng-submit="endEdit(list)">
<span id="mySpan">myNotMappedProperty: {{list.MyNotMappedProperty}}</span>
<input data-ng-model="list.title"
data-selected-when="list.isEditingListTitle"
data-ng-click="clearErrorMessage(list)"
data-on-blur="endEdit(list)"/>
</form>
</header>
...
在.Net POCO类TodoList中我添加
[NotMapped]
public string MyNotMappedProperty { get { return "testString"; } }
在todo.model.js
我修改构造函数如下:
function TodoList() {
this.title = "My todos"; // defaults
this.userId = "to be replaced";
this.MyNotMappedProperty = "";
}
现在,如果您运行应用程序并成功登录,{{list.MyNotMappedProperty}}
会显示空字符串,如果您再按“获取待办事项”按钮,{{list.MyNotMappedProperty}}
会显示值“testString”。
在这两种情况下,查询都是相同的,返回的Json如下:
[{"$id":"1","$type":"TodoTest.Models.TodoList, TodoTest","TodoListId":5,"UserId":"kostas","Title":"My todos","MyNotMappedProperty":"testString","Todos":[{"$id":"2","$type":"TodoTest.Models.TodoItem, TodoTest","TodoItemId":4,"Title":"dasdas","IsDone":false,"TodoListId":5,"TodoList":{"$ref":"1"}}]}]
我想在没有按下我添加的按钮的情况下首先显示“testString”。
我不知道我提供的信息是否足以重现行为,所以如果您需要任何其他信息,请告诉我。
谢谢。