4

データ モデルに型ごとのテーブルの継承を実装しました (基本的BaseEntityに、アイテムのすべての基本情報を含むEmployer型と、アイテムから継承する型がありBaseEntityます)。すべてが正しく設定されているように見え、エンティティを使用すると (ADO.net Data Services または Linq to Entities を介して)、Employerタイプと問題がないように見えます。新しいEmployerエンティティを作成して保存しようとすると、問題が発生します。

.AddToEmployerアイテムのように見えないコンテキスト(およびAddObjectまたはのみAddToBaseEntity)。

使用するAddObject("Employer", NewEmployer)と、次のエラーメッセージが表示されます。

EntitySet 名 'DataEntities.Employer' が見つかりませんでした。

使用するAddToBaseEntity(NewEmployer)と、次のエラーメッセージが表示されます。

依存操作の有効な順序を判別できません。外部キーの制約、モデルの要件、またはストアによって生成された値が原因で、依存関係が存在する場合があります。

継承を設定する手順を見逃していませんか? 継承されたオブジェクトを保存する特定の方法はありますか? 私は何を間違っていますか?基本的な問題は、 が必要だということだとAddToEmployer思いますが、それを公開するにはどうすればよいですか? クライアント側で Employer タイプを確認でき、次のようなことができるため、オプションではないのは奇妙に思えます。

var NewEmployer = new Employer()- これは、Employer タイプが正常に表示されることを示唆しているようです。

4

5 に答える 5

7

私の名前は Phani です。ADO.NET データ サービス チームで働いています。

ResolveNameおよびResolveTypeメソッドは、クライアントがサーバーに送信されるペイロードに書き込むタイプ情報と、サーバーからの応答ペイロードが具体化される方法をカスタマイズするのに役立ちます。

これらは、クライアントで型を解決するのに役立ち、多くのシナリオで役立ちます。いくつかの例を次に示します。

  1. エンティティのタイプ階層は、サーバーとは異なります。
  2. サービスによって公開されるエンティティ型は継承に参加し、クライアントで派生型を操作したい。

ResolveNameサーバーにリクエストを送信するときに送信するエンティティの名前を変更するために使用されます。

このデータモデルを検討してください: サーバー上

public class Employee {
    public int EmployeeID {get;set;}
    public string EmployeeName {get;set;}
}

public class Manager:Employee {
    public List<int> employeesWhoReportToMe {get;set;}
}

クライアントを使用して Manager Entity Type のインスタンスを操作する場合、変更をサーバーに送信するときに、エンティティが継承に参加するときにペイロードにタイプ情報が存在することが期待されます。

context.AddObject("Employees",ManagerInstance ); <-- add manager instance to the employees set.
context.SaveChanges();

ただし、クライアントがこのペイロードをシリアル化すると、サーバーで予期されていないタイプ名として「Employee」が挿入されます。したがって、クライアントに名前リゾルバーを提供する必要があります。

context.ResolveName = delegate(Type entityType){
    //do what you have to do to resolve the type to the right type of the entity on the server
    return entityType.FullName;
}

タイプ リゾルバも同様に使用されます。

context.ResolveType = delegate(string entitySetName){
    //do what you have to do to convert the entitysetName to a type that the client understands
    return Type.GetType(entitySetName);
}
于 2008-12-15T19:45:39.717 に答える
2

エンティティ セット pr しか取得できません。基本クラスなので、.AddToBaseEntity はそのようなソリューションです。

しかし、モデルに循環依存関係があるように思われるため、Entity フレームワークは保存する順序を判断できません。

派生エンティティの baseentity への外部キーがあることを確認し、モデルを更新します。

于 2008-10-17T09:44:29.517 に答える
2

私はいくつかのことを変更し、これを機能させることができました。基本的な問題が何であったかは特にわかりませんが、参考のために何をしたかを投稿したかったのです。

テーブルの再構築: ID/キー列と 1 つのデータ列だけから始めて、テーブルを再構築しました。

追加の自動インクリメント フィールドの削除: BaseEntity と Employer に自動インクリメント ID がありました。雇用主の自動インクリメント ID を削除し、Employer.BaseEntityID 列と外部キーを BaseEntity.BaseEntityID に戻しました。(これが原因だったようですが、これは許されているという印象を受けました)

残念ながら、これはエンティティ フレームワークの継承されたクラスがナビゲーション プロパティを持つことができない (すべてのナビゲーション プロパティは基本エンティティにある必要がある) という問題につながるため、継承はニーズに使用できないことが証明されます。

于 2008-10-22T04:19:52.213 に答える
1

エンティティタイプのように、エンティティセットとしてEmployerを定義していません。これは、コンテキストオブジェクトにAddToEntityがない方法です。1つのクラス階層に対して常に1つのエンティティセットがあります。この場合は、BaseClassエンティティセットです。

エンティティセット「Employer」を取得する場合は、edmxファイルを手動で編集し、新しいエンティティセット「Employer」を追加してから、エンティティタイプ「Employer」をそのエンティティセットに属するように設定できます。それは難しいことではないはずです、私はそれを何度もやりました。

もっと定期的な解決策があるかどうかはわかりません。

于 2008-10-17T07:43:49.183 に答える
1

2 年後に登場しますが、検索トラフィックとの関連性を維持するために、データベースにステージング データをすばやく入力するために使用していた便利なクラスで、これをすばやく回避する方法を次に示します。

以前のバージョンについてはわかりませんが、Entity Framework 4 では、オブジェクトをコンテキストに基本オブジェクトとしてダンプでき、フレームワークはサーバー側の参照を把握します。したがって、AddToInheritedObjects() (とにかく非推奨) を使用せずに、ObjectSet<>.Add() メソッドを使用します。

ヘルパー クラスの例を次に示します。

public ContextHelper
{
        …
        _context = ModelEntities();

        public T Create<T>() where T : class
        {
            // Create a new context
            _context = new ModelEntities();

            // Create the object using the context (can create outside of context too, FYI)
            T obj = _context.CreateObject<T>();

            // Somewhat kludgy workaround for determining if the object is
            // inherited from the base object or not, and adding it to the context's
            // object list appropriately.    
            if (obj is BaseObject)
            {
                _context.AddObject("BaseObjects", obj);
            }
            else
            {
                ObjectSet<T> set = _context.CreateObjectSet<T>();
                set.AddObject(obj);
            }

            return obj;
        }
        …
}

したがって、次のものがあると仮定します。

class ObjectOne : BaseObject {}
class ObjectTwo {}

エンティティをコンテキストに簡単に追加できます。

ContextHelper ch = ContextHelper()
ObjectOne inherited = ch.Create<ObjectOne>();
ObjectTwo toplevel = ch.Create<ObjectTwo>();
…

もちろん、ContextHelper には _context.SaveChanges() を呼び出す public Save() メソッドが必要であること、またはオブジェクトの変更をデータストアにプッシュする別の方法が必要であることを思い出してください。

これは、継承に関する特定の質問に対する直接的な回答ではないかもしれませんが、詳細に回答するための出発点になることを願っています。

于 2010-12-23T16:41:24.150 に答える