5

このエラーで立ち往生しており、これに対する解決策が見つかりません。私はいくつかのことを試しましたが、解決策を思い付くことができませんでした。

これが私の問題です:

コード:

namespace ProjectTracker.Database.Entities
{
    [DataContract]
    public class User
    {
        [DataMember]
        public int Id { get; set; }

        [Required]
        [MaxLength(50)]
        [DataMember]
        public string UserName { get; set; }

        [Required]
        [MaxLength(100)]
        [DataType(DataType.Password)]
        [DataMember]
        public string Password { get; set; }

        [DataMember]
        public bool IsPasswordExpired { get; set; }

        [Required]
        [DataMember]
        public DateTime CreatedDate { get; set; }

        [Required]
        [ForeignKey("CreatedBy")]
        [DataMember]
        public int CreatedByUserId { get; set; }

        [DataMember]
        public virtual User CreatedBy { get; set; }

        [Required]
        [DataMember]
        public DateTime LastUpdatedDate { get; set; }

        [ForeignKey("LastUpdatedBy")]
        [DataMember]
        public int? LastUpdatedByUserId { get; set; }

        [DataMember]
        public virtual User LastUpdatedBy { get; set; }
    }
}

Web サービスから呼び出しているときに取得する例外の詳細は次のとおりです。

リクエスト エラー サーバーでリクエストの処理中にエラーが発生しました。例外メッセージは、「モデルの生成中に 1 つ以上の検証エラーが検出されました: \tSystem.Data.Entity.Edm.EdmAssociationEnd: : 関係 'User_LastUpdatedBy' のロール 'User_LastUpdatedBy_Source' で多重度が無効です。従属ロール プロパティはキー プロパティではないため、従属ロールの多重度の上限は「*」である必要があります。'。詳細については、サーバー ログを参照してください。例外スタック トレースは次のとおりです。

System.Data.Entity.DbModelBuilder.Build (DbProviderManifest providerManifest、DbProviderInfo providerInfo) で System.Data.Entity.DbModelBuilder.Build (DbConnection providerConnection) で System.Data.Entity.Internal.LazyInternalContext.CreateModel (LazyInternalContext internalContext) で System. Data.Entity.Internal.RetryLazy 2.GetValue(TInput input) at System.Data.Entity.Internal.LazyInternalContext.InitializeContext() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSetSystem.Data.Entity.Internal.Linq.InternalSet で1.get_InternalContext() at System.Data.Entity.Infrastructure.DbQuery1.Initialize() System.Linq.Queryable.Where[TSource](IQueryable) で 1.System.Linq.IQueryable.get_Provider()1 source, Expression1 述語) e:\My Own\Projects\ProjectTracker\Database\ProjectTracker.Database.DataAccess\DLAccess.cs:line 31 at ProjectTracker.Business.BLAccess.BLAccess の ProjectTracker.Database.DataAccess.DLAccess.DoesUserExist(String userName) .DoesUserExists(String userName) in e:\My Own\Projects\ProjectTracker\Business\ProjectTracker.Business.BLAccess\BLAccess.cs:line 37 at ProjectTracker.UI.Web.WS.WebAccess.DoesUserExist(String userName) in e: \My Own\Projects\ProjectTracker\UI\ProjectTracker.UI.Web\WS\WebAccess.svc.cs: SyncInvokeDoesUserExist(Object , Object[] , Object[] ) の 12 行目 System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke( System.ServiceModel.Dispatcher の System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) のオブジェクト インスタンス、Object[] 入力、Object[]& 出力)。ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) で System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) で System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

私がここで間違っていることを教えてください...

4

1 に答える 1

11

EF マッピング規則は、 と の間の 1 対 1 の関係を推測しようとしUser.CreatedByますUser.LastUpdatedBy。これは、両方のナビゲーション プロパティが同時に主キーではない外部キーで表され、EF が共有主キーの 1 対 1 の関係のみをサポートするため、失敗します。

とにかく、これは重要ではありません。なぜなら、1 対 1 の関係ではなく、実際には 2 つの 1 対多の関係が必要だからです。ユーザーは他の多くのユーザーを作成でき、ユーザーは他の多くのユーザーを変更できます。

これを実現するには、Fluent API で 2 つの関係を明示的に定義して、規則をオーバーライドする必要があります。

modelBuilder.Entity<User>()
    .HasRequired(u => u.CreatedBy)  // this could be a problem, see below
    .WithMany()
    .HasForeignKey(u => u.CreatedByUserId);

modelBuilder.Entity<User>()
    .HasOptional(u => u.LastUpdatedBy)
    .WithMany()
    .HasForeignKey(u => u.LastUpdatedByUserId);

CreatedByをオプションにする必要がある場合があります。つまりCreatedByUserId、型int?である必要があり、上記のマッピングでは で置き換える必要があります。そうHasRequiredHasOptionalないと、FK 制約に違反せずに最初のユーザーを作成できなかったからです。

CreatedByUserIdおそらく、最初のユーザーを許可するNULL値でDBに直接作成し、このユーザーを自分の作成者として割り当て、DBスキーマを変更してNULL禁止するなどのトリックを適用できます。

編集

EF マッピング規則は、 と の間の 1 対 1 の関係を推測しようとしUser.CreatedByますUser.LastUpdatedByの詳細:

起動時に EF がモデル クラスを分析するときは、

  1. Fluent API を使用した構成、
  2. 適用されたデータ注釈、
  3. ナビゲーション プロパティとプロパティ名から関係を推測するための特定の規則のセット。

Fluent API またはデータ注釈で明示的に指定されていない限り、これらのセンベンションのセットが適用されます。ここで規則の完全なセットを見つけることができます: http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx

元のUserクラスの場合AssociationInverseDiscoveryConvention、モデルに適用され、1 対 1 の関係を検出するのは です。ドキュメントには次のように記載されています。

関連する型の間にナビゲーション プロパティのペアが 1 つだけ存在する場合に、ナビゲーション プロパティが互いに逆であることを検出するための規則。

ナビゲーション プロパティの "1 つだけ" のペアは、 -を参照するとCreatedBy、を参照する 2 番目のナビゲーション プロパティです。(「関連する型」が同じであるため、少し混乱しますが、ここでは、異なる型間と同じように規則が適用されます。) どちらも参照 (コレクションではない) であるため、EF は関係が 1 でなければならないと想定しています。対 1 (1 対多または多対多ではありません)。UserUserUserLastUpdatedByUserUserUser

場合によっては、慣習によって関係が思いどおりに推論されないことがあります。次に、Fluent API またはデータ注釈を使用してマッピング規則をオーバーライドする必要があります。(あなたの例では注釈は十分ではありません。ここでは Fluent API を使用する必要があります。)

于 2013-02-06T18:06:51.100 に答える