0

次のコードを使用します。

using (ICMSEntities db = new ICMSEntities())  
{  
    productObj.Sectors.Clear();  
    int[] selected_sectors = cblSectors.Items.Cast<ListItem>()  
        .Where(n => n.Selected).Select(n => Convert.ToInt32(n.Value)).ToArray();  
    for (int i = 0; i < selected_sectors.Length; i++)  
    {  
        int SectorID = selected_sectors[i];  
        Sector sectorObj = db.Sectors.SingleOrDefault(x => x.sector_id == SectorID);  
        productObj.Sectors.Add(sectorObj);  
        }  
    db.SaveChanges();  
    Response.Redirect("~/Products.aspx", true);  
}

多対多の関係テーブルを更新しようとしています。各セクターには一連の製品を含めることができ、各製品には一連のセクターを含めることができます。製品エンティティを更新しようとすると、ユーザーが上記のチェックボックス リストから他の使用可能なセクターを選択した場合に備えて、すべてのセクターをクリアしています.Clear()。次に、チェックボックスリストから読み取り、更新します。レコードを更新する代わりに、新しい自動インクリメント ID を持つ製品で新しい同一の行を取得しています。したがって、更新ではなく挿入を行っており、指定したことはありません.AddObject()

ここで何が間違っていますか?または、これを正しく実装するにはどうすればよいですか?

ありがとう。

4

2 に答える 2

0

これの代わりに:

Sector sectorObj = db.Sectors.SingleOrDefault(x => x.sector_id == SectorID);  

これを行う:

Sector sectorObj = db.Sectors.Find(SectorID);  

コードで とのデータベース ラウンドトリップを発生させたくない場合は.Find、代わりに次の LoadStub メソッドを使用します。

public static class Helpers
{
 
    public static Ent LoadStub<Ent>(this DbContext db, object id) where Ent : class
    {
        string primaryKeyName = typeof(Ent).Name + "Id";
        return db.LoadStub<Ent>(primaryKeyName, id);
    }
 
    public static Ent LoadStub<Ent>(this DbContext db, string primaryKeyName, object id) where Ent: class
    {
        var cachedEnt = 
            db.ChangeTracker.Entries().Where(x => ObjectContext.GetObjectType(x.Entity.GetType()) == typeof(Ent)).SingleOrDefault(x =>
            {
                var entType = x.Entity.GetType();
                var value = entType.InvokeMember(primaryKeyName, System.Reflection.BindingFlags.GetProperty, null, x.Entity, new object[] { });
 
                return value.Equals(id);
            });
 
        if (cachedEnt != null)
        {
            return (Ent) cachedEnt.Entity;
        }
        else
        {
            Ent stub = (Ent) Activator.CreateInstance(typeof(Ent));
 
             
            typeof(Ent).InvokeMember(primaryKeyName, System.Reflection.BindingFlags.SetProperty, null, stub, new object[] { id });
 
 
            db.Entry(stub).State = EntityState.Unchanged;
 
            return stub;
        }
 
    }
}

コードは次のようになります。

Sector sectorObj = db.LoadStub<Sector>(SectorID);  

使用例: http://www.ienablemuch.com/2011/07/using-checkbox-list-on-aspnet-mvc-with_16.html

于 2012-08-19T16:23:02.720 に答える
0

削除して再作成するのは良い考えではないと思います。また、使用Clearしてもデータベースからは削除されず、メモリからのみ削除されます。これがあなたがしなければならないことです:

using (ICMSEntities db = new ICMSEntities())  
{ 
    foreach (ListItem item in cblSectors.Items)
    {
        int SectorID = item.Convert.ToInt32(item.Value);
        if (item.Selected && !productObj.Sectors.Any(s => s.SectorID == SectorID))
        {
            Sector sectorObj = db.Sectors.Single(x => x.sector_id == SectorID);  
            productObj.Sectors.Add(sectorObj);  
        } 
        else if (!item.Selected && productObj.Sectors.Any(s => s.SectorID == SectorID))
        {
            var sector = productObj.Sectors.Single(s => s.SectorID == SectorID);
            productObj.Sectors.Remove(sector);
        }
    }
    db.SaveChanges();  
    Response.Redirect("~/Products.aspx", true);  
}
于 2012-08-19T16:23:28.427 に答える