Używam Entity Framework 6.1.3 i mam scenariusz, w którym pobieram obiekt z jego nawigacją nieruchomość (za pomocą include()) i odłączyć je od kontekstu, zmienić klucz obcy Id następnie ponownie podłączyć go do nowego DbContext:Kod EF 6 Po pierwsze, zmiana identyfikatora klucza obcego z właściwością Włącz na nawigacji powoduje "Naruszenie ograniczenia więzów integralności" Błąd
// Init the Db
using (var db = new MyContext())
{
var theWarranty = new ProductWarranty { WarrantyName = "The Warranty" };
var newWarranty = new ProductWarranty { WarrantyName = "New Warranty" };
var brand = new ProductBrand { BrandName = "The Brand", DefaultWarranty = theWarranty };
db.ProductBrands.Add(brand);
db.ProductWarranties.Add(newWarranty);
db.SaveChanges();
}
// Load the detached Brand
ProductBrand detachedBrand;
using (var db = new MyContext())
{
detachedBrand = db.ProductBrands.AsNoTracking()
.Include(b => b.DefaultWarranty) // <<< If this line is removed the Attach works
.First(x => x.Id == 1);
}
// Modify the Default Warranty Foreign Key
detachedBrand.DefaultWarranty = null;
detachedBrand.DefaultWarranty_Id = 2;
// Attempt to re-attach and save the changes
using (var db = new MyContext())
{
var entity = db.Set<ProductBrand>().Attach(detachedBrand); // <<< This line throws the exception
db.Entry(entity).State = EntityState.Modified;
db.SaveChanges();
}
dostaję:
więzów integralności Wystąpiło naruszenie ograniczenia: Wartość (wartości) właściwości> "ProductWarranty.Id" na jednym końcu relacji nie pasuje do właściwości> wartości produktu "ProductBrand.DefaultWarranty_Id" na drugim końcu.
Jednakże, jeśli NIE użyję funkcji Uwzględnij(), załącz działa dobrze.
Potrzebuję właściwości nawigacji (DefaultWarranty) w realnym scenariuszu, ale nie widzę różnicy w włączaniu nawigacji w oddzielonym obiekcie, zamiast ładowania go w odłączonym obiekcie. Z mojego doświadczenia i czytania powinno wynikać ustawienie klucza obcego na nową wartość i ustawienie właściwości nawigacji na wartość null.
Przeczytałem na blogu Ladislava o filmie Klucz obcy kontra własność niezależna http://www.ladislavmrnka.com/2011/05/foreign-key-vs-independent-associations-in-ef-4/, ale nie radzę sobie z tym scenariuszem iz tego, co mogę powiedzieć, używam w tym przypadku kluczy obcych.
Co się dzieje i jaki jest właściwy sposób radzenia sobie ze zmianą kluczy obcych przy uwzględnieniu właściwości nawigacji, takich jak ten scenariusz?
To prawie tak, jakby EF nie "w pełni" odłączyło obiektu, gdy użyto Include ... co również wydaje się dziwne.
Oto uproszczona konfiguracja:
Marka produktu
public partial class ProductBrand
{
public int Id { get; set; }
public string BrandName { get; set; }
public Nullable<int> DefaultWarranty_Id { get; set; }
public virtual ProductWarranty DefaultWarranty { get; set; }
}
Marka produktu Mapa
public class ProductBrandMap : EntityTypeConfiguration<ProductBrand>
{
public ProductBrandMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Properties
this.Property(t => t.BrandName)
.IsRequired()
.HasMaxLength(40);
// Table & Column Mappings
this.ToTable("ProductBrands");
this.Property(t => t.Id).HasColumnName("Id");
this.Property(t => t.BrandName).HasColumnName("BrandName");
this.Property(t => t.DefaultWarranty_Id).HasColumnName("DefaultWarranty_Id");
// Relationships
this.HasOptional(t => t.DefaultWarranty)
.WithMany(t => t.ProductBrands)
.HasForeignKey(d => d.DefaultWarranty_Id)
.WillCascadeOnDelete(false);
}
}
gwarancji produktu
public partial class ProductWarranty
{
public ProductWarranty()
{
this.ProductBrands = new List<ProductBrand>();
}
public int Id { get; set; }
public string WarrantyName { get; set; }
public virtual ICollection<ProductBrand> ProductBrands { get; set; }
}
Gwarancja produktów Mapa
public class ProductWarrantyMap : EntityTypeConfiguration<ProductWarranty>
{
public ProductWarrantyMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Properties
this.Property(t => t.WarrantyName)
.IsRequired()
.HasMaxLength(40);
// Table & Column Mappings
this.ToTable("ProductWarranties");
this.Property(t => t.Id).HasColumnName("Id");
this.Property(t => t.WarrantyName).HasColumnName("WarrantyName");
}
}
Przetestowałem to i działa bez żadnego wyjątku! – Alireza
@Alireza - Specyfikacje mojego dewelopera i projektu to VS2013, .net 4.5.2. Ponownie uruchomiłem kod i nadal dostaję błąd. Wysłałem również mój projekt do innego programisty i on sam zachowuje się tak samo ... i jest równie zakłopotany jak ja. Czy podjąłeś konkretne kroki w celu uruchomienia kodu? – mips
Czy wysłałbyś mi swój projekt? – Alireza