2012-12-08 17 views
17

Code-First DBContext tabanlı EF5 kurulumunu kullanıyorum.AddOrUpdate beklendiği gibi çalışmaz ve çoğaltmalar üretiyor

DbMigrationsConfiguration.Seed içinde DB'yi varsayılan dummy verileriyle doldurmaya çalışıyorum. Bu görevi gerçekleştirmek için DbSet.AddOrUpdate yöntemini kullanıyorum.

en basit kod amacım göstermek için:

Ben güncelleme seçicisi olarak Id/ Slug özelliğini kullanmak kadar/kullanmak ve ayrıca Id alanının göz ardı edilmesi denedim
j = 0; 

var cities = new[] 
    { 
     "Berlin", 
     "Vienna", 
     "London", 
     "Bristol", 
     "Rome", 
     "Stockholm", 
     "Oslo", 
     "Helsinki", 
     "Amsterdam", 
     "Dublin" 
    }; 
var cityObjects = new City[cities.Length]; 


foreach (string c in cities) 
{ 
    int id = r.NextDouble() > 0.5 ? 0 : 1; 
    var city = new City 
     { 
      Id = j, 
      Name = c, 
      Slug = c.ToLowerInvariant(), 
      Region = regions[id], 
      RegionId = regions[id].Id, 
      Reviewed = true 
     }; 
    context.CitySet.AddOrUpdate(cc => cc.Id, city); 
    cityObjects[j] = city; 
    j++; 
} 

. çalıştırıldığında, Id alanı yoksayılır ve değer SQL Server tarafından otomatik olarak oluşturulur ve DB çiftler ile doldurulur; Slug seçici çoğaltmaya izin verir ve sonraki çalıştırmalarda istisnalar oluşturur (Sequence contains more than one element).

AddOrUpdate yöntemi bu şekilde çalışmak üzere tasarlanmıştır? Ben elimden geleni yapmalı mıyım? Sadece tip City[] bir dizi oluşturmak ve bir kez context.CitySet.AddOrUpdate(cc => cc.Id, cityArray); çağrı böylece

cevap

26

First (yanıt yok henüz), AddOrUpdate, yeni nesnelerin bir dizi çağrılabilir. (Düzenlenmiş)

İkinci olarak, AddOrUpdate dizideki olanlar aynı Id ile şehirler bulmak için tanımlayıcı ifade (cc => cc.Id) kullanır. Bu şehirler güncellenecek. Dizideki diğer şehirler eklenir, ancak Id değerleri Id bir kimlik sütunu olduğundan, veritabanı tarafından Id değerleri oluşturulur. Ekleme ifadesiyle belirlenemez. (Kimlik Ekleme'yi ayarlamadığınız sürece). Yani kimlik sütunları olan tablolar için AddOrUpdate kullanırken, kayıtları tanımlamanın başka bir yolunu bulmanız gerekir, çünkü varolan kayıtların Id değerleri önceden kestirilemez.

AddOrUpdate için Slug tanımlayıcısını kullanmış olmanız durumunda, benzersizdir (yorumunuza göre). Slug s ile eşleşen kayıtların neden güncellenmediği bana açık değil.

senin küçük bir testten kurmak:

var n = new Product { ProductID = 999, ProductName = "Prod1", UnitPrice = 1.25 }; 
Products.AddOrUpdate(p => p.ProductName, n); 
SaveChanges(); 

"Prod1" o (İd 999 görmezden takıldığında, henüz yoktur: bir kimliği (iedntity) ve benzersiz bir adla bir varlık eklemek veya güncellemek).
UnitPrice farklıysa, güncelleştirilir.

SELECT TOP (2) 
[Extent1].[ProductID] AS [ProductID], 
[Extent1].[ProductName] AS [ProductName], 
[Extent1].[UnitPrice] AS [UnitPrice] 
FROM [dbo].[Products] AS [Extent1] 
WHERE N'Prod1' = [Extent1].[ProductName] 

Ve gelecek (Bir eşleşme bulunduğunda ve UnitPrice farklıdır)

update [dbo].[Products] 
set [UnitPrice] = 1.26 
where ([ProductID] = 15) 

Bu:

Ben EF adıyla benzersiz plak istiyor görüyoruz yayılan sorguları baktığımızda EF'nin bir kayıt bulduğunu ve şimdi güncellemeyi yapmak için anahtar alanını kullandığını gösteriyor.

Umarım bu örneği görmek sizin durumunuza ışık tutacaktır. Belki de sql ifadelerini izlemeli ve beklenmedik bir şey olup olmadığını görmelisiniz.

+0

Gert, yardım etmeye çalışıyorum için teşekkür ederim! Aslında, Şehir, 0'dan 9'a kadar değişen "id = j" oldu. Siz sadece benzer değişken isimleriyle kandırıldınız. Daha sonra, İsim kullanmanın etkilerinden bahsetmiştim (benim durumumda, Slug, gerçekten benzersiz olduğu gibi) - DB'ye kopyalanmasına izin veriyor. Tüm nesneleri bir dizi olarak geçmek hiçbir ilerleme göstermedi. – berezovskyi

+0

Cevabınızı güncellediğiniz için teşekkürler. Artık bunu doğrulayamıyorum. Eğer topluluğun herhangi biri cevabınız altında ona yardımcı olduğunu belirttiyse, cevabınızı kabul edildi olarak işaretleyeceğim. Üzgünüm çok uzun sürdü. – berezovskyi

+1

Kayıtların benzersiz bir şekilde tanımlanması için iki alanın gerekip gerekmediğine dair tanımlayıcı ifadesinin nasıl görüneceği hakkında bir fikriniz var mı? Ben p => p.ProductName, p.CategoryName düşünüyorum (ama tabii ki çalışmıyor). Eğer gerçek DBSet başvurmak zorunda '' context.Set () .AddOrUpdate (...) kullanırken – Jarvis

1
var paidOutType = new List<PaidOutType> 
       { 
        new PaidOutType { PaidOutTypeID = 1, Code = "001", Description = "PAID OUT 1", PType = "1", Amount = 0, IsSalesSummery = true,DayFrom=1,DayTo=31 }, 
        new PaidOutType { PaidOutTypeID = 2, Code = "002", Description = "PAID OUT 2", PType = "1", Amount = 0, IsSalesSummery = true,DayFrom=1,DayTo=31 }, 
        new PaidOutType { PaidOutTypeID = 3, Code = "002", Description = "PAID OUT 3", PType = "1", Amount = 0, IsSalesSummery = true,DayFrom=1,DayTo=31 }, 
       }; 
       paidOutType.ForEach(u => smartPOSContext.PaidOutType.AddOrUpdate(u)); 
       smartPOSContext.SaveChanges(); 
İlgili konular