4

Entity Frameworkに、両側がオプション(0..Mから0..N)である多対多の関係をモデル化する方法はありますか(データ注釈がいくらか制限されているため、流暢な構文になると思います)。関係)?ユースケースは次のとおりです。ユーザーがエンティティにタグを追加できるようにします。エンティティへのタグはM:N関係ですが、どちらも必須ではありません。つまり、どのエンティティにも適用されないタグが存在する可能性があり、エンティティのタグが解除される可能性があります。これは私にはかなり合理的なようです。これを使用して単純にモデル化することはできません。

public virtual ICollection<Tag> Tags { get; set; }

public virtual ICollection<Entity> Entities { get; set; }

各クラスには他の関係があり、「外部キー制約によりサイクルまたは複数のカスケードパスが発生する可能性がある」ためです。私は多分私が次のようなことをすることができることを望んでいました:

modelBuilder.Entity<Tag>().HasOptional(t => t.Entities);
modelBuilder.Entity<Entity>().HasOptional(t => t.Tags);

しかし、EFは「協会の主要な目的を決定することができない」と警告されています。読んでみると、そのような関係には主要な目的がなければならないようですが、私の場合、それは望ましくありません。

ブリッジテーブルを表すクラスを追加し、マッピングを手動で処理することもできますが、コードが乱雑にならないようにしたいと思います。EFでこれをモデル化する別の方法があるかどうか疑問に思いました。

もう少し詳しく入力するために、Authorクラス(Usersに相当)もあります。作成者とタグは1:Mであり、エンティティへの作成者も1:Mです。もちろん、問題は、Entitiesクラスがカスケードツリーで2回発生することです。タグ/エンティティの関係をオプションにすると、これが修正されます。エンティティを介してタグにアクセスする方法があれば修正することもできますが、タグはエンティティに接続していなくても存在できるため、それは不可能だと思いました。

関連するコードの概要は次のとおりです。

public class Author
{
    public Guid Id { get; set; }
    public virtual List<Entity> Entities { get; set; }
    public virtual List<Tag> Tags { get; set; }
}

public class Tag
{
    public Guid Id { get; set; }
    public Guid AuthorId { get; set; }
    public virtual Author Author { get; set; }
    public virtual ICollection<Entity> Entities { get; set; }
}

public class Entity
{
    public Guid Id { get; set; }
    public Guid AuthorId { get; set; }
    public virtual Author Author { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }
}

編集:

以下に提案されているように使用.HasMany().WithMany()すると、これが得られます。

CREATE TABLE [dbo].[TagEntities] (
    [Tag_Id] [uniqueidentifier] NOT NULL,
    [Entity_Id] [uniqueidentifier] NOT NULL,
    CONSTRAINT [PK_dbo.TagEntities] PRIMARY KEY ([Tag_Id], [Entity_Id])
)

しかし、私が望んでいるのは、Tag_IdとEntity_Idがこのテーブルでnull許容であることです。たぶん、このモデルは私が思ったほど意味がありませんか?両側がnull許容のブリッジテーブルを作成できますか?

4

2 に答える 2

3

使用する

modelBuilder.Entity<Tag>().HasMany(t => t.Entities)
    .WithMany(t => t.Tags);

それ以外の

modelBuilder.Entity<Tag>().HasOptional(t => t.Entities);
modelBuilder.Entity<Entity>().HasOptional(t => t.Tags);
于 2013-01-14T03:50:46.380 に答える
0

これが正しい答えかどうかはわかりませんが、他のクラスが継承する DbEntity という基本クラスを作成することでこれを解決しました。したがって、著者は次のようになります。

// Both entities and tags are part of this collection
public virtual List<DbEntity> Entities { get; set; }

「エンティティ」(私のコードでは特別な意味があります) と「タグ」サブクラス DbEntity の両方。これにより、ナビゲーション プロパティを維持しながら複数のカスケード パスが排除されましたが、これを行う必要はあります。

author.Entities.OfType<Tag>();

また

author.Entities.OfType<Entity>();

特定のエンティティのセットを取得します。

于 2013-01-17T17:45:51.167 に答える