0

Visual Studio 2012 で Angular/Breeze SPA テンプレートを使用しています。TodoList サーバー モデルにマップされていないプロパティを追加しました。

[NotMapped]
public string MyUnmappedProperty{ get{return "testString";}} 

クライアント モデルのコンストラクター、具体的にはウォードがここで提案したように todo.model.js にマップされていないプロパティを登録しました

function TodoList() {
        this.title = "My todos"; // defaults
        this.userId = "to be replaced";
         this.myUnmappedProperty="";
    }

todo.controller.js で getTodos() メソッドが初めて呼び出されたとき、「myUnmappedProperty」には、コンストラクターで設定された空の文字列の値が含まれます。getTodos() が 2 回目に呼び出された後にのみ (それを行うボタンを追加しました)、「forceRefresh」を true (getTodos(true)) に設定してサーバーにクエリを実行すると、myUnmappedProperty が値を取得するのがわかります。 「テスト文字列」。

なぜ私はこのような行動をとっているのか疑問に思っています。getTodos() が初めて呼び出されたときに、マップされていないプロパティにサーバーの値を入力することは可能ですか?

ありがとうございました。

4

3 に答える 3

2

この問題の解決策は見つかりましたか? 私は同じ問題に苦しんでおり、最近、CassidyK によるこの SO 投稿を見つけました。この投稿では、Breeze ソース コード (breeze.debug.js) の 1 行を変更することで、非常によく似た問題を解決しています。彼が変更したコード スニペットは次のとおりです (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 = { };
    }
};

私はこの解決策を試しましたが、うまくいくようです。データベースにマップされていないサーバー側のプロパティがあり、オブジェクトがクライアント側で作成されるときにクライアント側でこの値を上書きする必要がある場合、この変更によりおそらく問題が発生することに注意してください。

于 2013-11-07T09:18:39.940 に答える
1

読者のためのいくつかの背景。

差別化が大事

  • EF の観点から「マップされていない」
  • Json.Net の観点から見た「シリアル化されていない」
  • Breeze の観点から見た「マッピングされていない」

[NotMapped]EF に「このプロパティはデータベースにマップされていません」と伝える EF 属性です。

[JsonIgnore]は、JSON.Net に「クライアントに送信するときにこのプロパティをシリアル化しないでください」と指示する Json.Net 属性です。

どのプロパティが「マッピング」されているかを Breeze に伝えることができるのは、メタデータだけです。

通常、Breeze は、メタデータで定義されている受信プロパティを無視します。ただし、メタデータ以外のプロパティがコンストラクターで定義されている場合、Breeze はそれをメタデータに追加し、「マップされていない」として分類します。

Breeze の場合、「このプロパティをシリアル化し、変更時に UI に通知しますが、これはエンティティのデータ モデルの一部ではなく、変更を追跡する必要はありません (つまり、変更は EntityState に影響しません)」 。

あなたの質問を理解するために、これらのアイデアをまとめてみましょう

MyUnmappedPropertyプロパティをマップしないように EF に指示しました。プロパティがメタデータにも含まれないように、おそらく を使用しEFContextProviderてメタデータを生成しています。

しかし、Json.Net はこれについて何も知りません。したがって、 のインスタンスをシリアル化するたびにTodoListMyUnmappedPropertyプロパティ (「testString」) が Breeze クライアントに送信されます。

最初、Breeze は何もしません。サーバーがこのプロパティに任意の値を送信しても、Breeze はそれを無視します。

MyUnmappedPropertyしかし、型コンストラクターにプロパティを 追加したTodoListので、Breeze はこのプロパティを「マップされていない」ものとして認識し、JSON クエリ結果に表示される場合はその値を具体化します。

TodoList(newまたはを使用して)の新しいインスタンスを作成するとentityManager.CreateEntity(...)MyUnmappedPropertyプロパティは''ctor ごとに設定されます。

に対してクエリを実行するTodoListと、Json.NET{MyUnmappedProperty: "testString}は JSON の結果を送信します。Breeze クライアントは を認識しMyUnmappedProperty、それに応じて具体化されたTodoListエンティティ インスタンスにそのプロパティを設定します。

それが起こるはずです。

「testString」ではないようなクエリTodoList実体化されることを実証できますか?MyUnmappedProperty

ネットワーク トラフィックを確認したところ、{MyUnmappedProperty: "testString}実際にはネットワーク経由で送信されているのに実現されていないことがわかりましたか? そして、あなたはそれが2番目のクエリで具体化されていると言いますか?.

その再現が必要です!

于 2013-08-03T21:00:15.213 に答える
0

@区、あなたの答えをありがとう。

まず、Breeze バージョン 1.4.0 を使用していることを忘れていました。

ネットワーク トラフィックを確認したところ、{MyUnmappedProperty: "testString} が実際にネットワーク経由で送信されていることがわかりました 。はい、確認しました。サーバーから送信された JSON に含まれています。

私が経験している動作を得るには、スパ テンプレートに 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}}、空の文字列が表示されます。次に [Get Todos] ボタンを押すと {{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」を取得したいと思います。

私が提供した情報が動作を再現するのに十分かどうかわからないので、追加情報が必要な場合は教えてください.

ありがとうございました。

于 2013-08-06T12:43:14.207 に答える