2

現在問題が発生しており、解決策がないように見えるスタックオーバーフローを高低で検索しました。何か間違ったことをしているに違いないと思いますが、誰かが助けてくれることを願っています。

とにかく、私は次のモデルを持っています:

public abstract class IDObject
{
    [Key]
    public Guid ID { get; set; }
}

public class TV : IDObject
{
    public TV()
    {
        this.Channels = new List<Channel>();
    }
    public string Name { get; set; }
    public virtual IList<Channel> Channels { get; set; } 
}

public class Channel : IDObject
{
    public string Name { get; set; }
    public int Number { get; set; }
    [Navigational]
    public virtual IList<TV> TVs { get; set; }  
}

テレビ - チャンネルは多対多の関係である必要があります。

基本的に、テレビとチャンネルをデータベースに追加し、コンテキストを破棄し、テレビが以前に追加されたチャンネルを参照してから、データベース エンティティを更新できるようにしたいと考えています。

何かのようなもの:

TV someTV = new TV() { ID = Guid.NewGuid(), Name = "myBigTV" };
Channel chan1 = new Channel() { ID = Guid.NewGuid(), Name = "CBC", Number = 3};

using (ReferenceContext context = new ReferenceContext())
{
    context.TVs.Add(someTV);
    context.Channels.Add(chan1);
    context.SaveChanges();
}

someTV.Name = "myBigTV updated";
someTV.Channels.Add(chan1);

using (ReferenceContext context = new ReferenceContext())
{
    context.TVs.Attach(someTV);
    context.Entry(someTV).State = EntityState.Modified;
    *** some code here ***
    context.SaveChanges();
}

これを行うと、someTV エンティティが更新されますが、データベースで「検索」呼び出しを行うと、チャネルへの参照がまだありません。

今、チャネルの DbCollectionEntry で .Load() を試しました。コンテキスト内の someTV からチャネルへのすべての参照を削除してから、それらを再度追加しようとしました。参照したチャンネルの EntityState を someTV から Modified に変更しようとしましたが、何も機能しないようです。

私は最初にコードを使用しており、データベースは次のテーブルを作成しています:

Channels
ChannelTVs
TVs

チャンネルと TV はどちらも問題ないように見えますが、結合テーブル 'ChannelTVs' は何をしても常に空です。

質問 1: このシナリオで関連付けを更新する標準的な方法は何ですか。必ずしもチャネル自体を更新する必要はありません。基本的には、結合テーブルからエンティティを追加/削除するだけです。これらの変更を取得するには、流暢な API に何かを追加する必要がありますか?

質問 2: これを一般的な方法で行う方法はありますか? 私の現在の更新は次のようになります。

void Update<TDatabase>(IDatabaseContext context, TDatabase item)
{
    IDbSet<TDatabase> dbSet = context.GetDbSet<TDatabase>();
    dbSet.Attach(item);
    context.Entry(item).State = EntityState.Modified;
    context.SaveChanges();
}

このような質問が以前にも寄せられたことは知っていますが、どの解決策もうまくいかないようです。それは私が間違っていることかもしれませんし、あるいは単に特別なケースかもしれません...

ありがとう。

4

1 に答える 1

0

誰かがこれを見つけて、その方法に興味がある場合...私はなんとか一般的な解決策を見つけることができました。きれいではありませんが、機能します。

update()
{
    using (ReferenceContext context = new ReferenceContext())
    {
        TV newTV = context.TVs.Single(x => x.ID == someTV.ID);
        DbEntityEntry entityEntry = context.Entry(newTV);
        entityEntry.CurrentValues.SetValues(someTV);
        UpdateReferences(context, entityEntry, someTV);
        context.SaveChanges();
    }
}

private static void UpdateReferences(ReferenceContext context, DbEntityEntry entityEntry, IDObject someObject)
{
    List<PropertyInfo> properties = someObject.GetType().GetProperties().Where(prop => !prop.IsDefined(typeof(NavigationalAttribute), false) && prop.PropertyType.GetInterfaces().Any(type => type == typeof(IEnumerable)) && prop.PropertyType.GetGenericArguments().Any()).ToList();

    foreach (PropertyInfo property in properties)
    {
        IList references = (IList)property.GetValue(someObject, null);
        DbCollectionEntry newCollection = entityEntry.Collection(property.Name);


        var method = typeof(TestEF).GetMethod("Wrapped", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(property.PropertyType.GetGenericArguments()[0]);

        method.Invoke(null, new object[] { context, newCollection.CurrentValue, references });
    }
}

private static void Wrapped<T>(ReferenceContext context, IList<T> container, IEnumerable<T> references) where T : IDObject
{
    container.Clear();
    var dbSet = context.GetDbSet<T>();
    foreach (var referencedObject in references)
    {
        T item = dbSet.Find(referencedObject.ID);
        container.Add(item);
    }
}
于 2013-04-24T14:11:41.067 に答える