2

これが以前に尋ねられたことがあれば、私を許してください。数回検索した後、近いものは見つかりませんでした:

IQueryable を「インターセプト」し、実行時にすべての親子関係を無効にする ActionFilter を MVC に記述しようとしています。私がこれを行っているのは、親子関係がある場合、Linq がオブジェクトを適切にシリアル化しないためです (親が子を参照し、子が親を参照するため、循環参照エラーがスローされます)。オブジェクトが必要です。 Ajax 呼び出しのために Json にシリアライズされます。内部のプライバシー ステータスで DBML ファイルの子関係をマークしようとしました。これによりシリアル化の問題が修正されますが、ページのレンダリング時にビュー エンジンから子メンバーが非表示になり、別のエラーがスローされます。したがって、1 つの問題を修正することで、別の問題を引き起こします。

両方の問題を解決する唯一の方法は、シリアル化を返す直前に子メンバーを手動で null に設定することですが、面倒で再利用できないなどの理由で、それを避けようとしています。シリアル化されている IQueryable を使用し、EntitySet のタイプを持つメンバーを無効にします (外部キー/関連付けの表現方法)。ただし、私はリフレクションの経験があまりなく、このようなことを行う方法を示す例を見つけることができません。それで...これはリフレクションで可能ですか?同じことを達成するためのより良い方法はありますか? 明日、仕事用のコンピューターに戻ったら、関連するコードを投稿します。

ありがとう、

ダニエル


約束通り、コード:

[GridAction]  
public ActionResult _GetGrid()  
{  
  IQueryable<Form> result = formRepository.GetAll();  
  foreach (Form f in result)  
    {
      f.LineItems = null;
      f.Notes = null;
    }

  return View(new GridModel<Form> { Data = result });
}

追加のしわは、私が新しい Telerik MVC 拡張機能を使用していることです。そのため、実際には Json を自分でシリアル化していません。IGridModel で IQueryable を返すだけで、アクション フィルター [GridAction] が残りの処理を行います。

4

2 に答える 2

1

興味のある方のために、私が最終的にこの問題を解決した方法を次に示します。Damien Guard の T4 テンプレートを変更して、Association 型のエンティティの上に属性 [ScriptIgnore] を含めました。これにより、JSON シリアライザーはこれらをシリアライズしないことを認識し、循環参照の問題を回避できます。生成されたコードは次のようになります。

private EntitySet<LineItem> _LineItems;
    [ScriptIgnore]
    [Association(Name=@"Form_LineItem", Storage=@"_LineItems", ThisKey=@"Id", OtherKey=@"FormId")]
    public EntitySet<LineItem> LineItems
    {
        get {
            return _LineItems;
        }
        set {
            _LineItems.Assign(value);
        }
    }

これにより、LINQ を介した子テーブルの使用を無効にすることなく、私が抱えていたシリアル化の問題が修正されます。コントローラーのグリッド アクションは、次のようになります。

[GridAction]
public ActionResult _GetGrid()
{
  return View(new GridModel<Form> { Data = formRepository.GetAll() });
}
于 2009-11-11T19:26:28.960 に答える
0

2 つのオプションがあります。1 つは、 を使用したシリアル化中にこれらのプロパティを無視すること[XmlIgnore]です。もう 1 つは、リフレクションを使用してプロパティを無効にすることです。

シリアライゼーションで無視する、シリアライゼーションでデフォルト値を使用する方法を示す簡単な使用例:

[Serializable]
public class MyClass
{
    [XmlIgnore]
    public int IgnoredVal { get; set; }

    public int Val { get; set; }
}

public void UsageSample()
{
    var xmlSerializer = new XmlSerializer(typeof(MyClass));
    var memoryStream = new MemoryStream();
    var toSerialize = new MyClass { IgnoredVal = 1, Val = 2 };
    xmlSerializer.Serialize(memoryStream, toSerialize);
    memoryStream.Position = 0;
    var deserialize = (MyClass)xmlSerializer.Deserialize(memoryStream);

    Assert.AreEqual(0, deserialize.IgnoredVal);
    Assert.AreEqual(2, deserialize.Val);
}

リフレクションで無効化、コード サンプル:

public void NullifyEntitySetProperties(object obj)
{
    var entitySetProperties = obj.GetType().GetProperties()
        .Where(property => property.PropertyType == typeof(EntitySet));

    foreach (var property in entitySetProperties)
    {
        property.SetValue(obj, null, null);
    }
}

私の意見では、最初のオプションをコードで使用できるのであれば、それはより良いことです。このオプションは、より直接的で経済的です。

于 2009-11-11T05:28:16.580 に答える