问题描述
我不得不承认,EF 4.1 RC Codefirst,DataAnnotations和FluentAPI的功能仍然压倒我。有时我真的不知道我在做什么;-)请参阅以下POCO: public class国家
{
[Key]
public Guid ID {get;组;
[必需]
public virtual货币货币{get;组;
}
public class货币
{
[Key]
public Guid ID {get;组; }
public virtual ICollection< Country>国家{get;组; }
}
一般想法:每个国家都需要一个货币。但是,一个货币根本不需要分配给一个国家。
如果让EF创建相应的数据库,那么关系将按照惯例设置为CASCADE DELETE。换句话说:如果您删除货币,相应的国家/地区也将被删除。但是在我的情况下,这不是我想要的。
我在FluentAPI中提出了一些代码,以便禁用CASCADE DELETE:
modelBuilder.Entity< Country>()
.HasRequired(cou => cou.Currency)
.WithOptional()
.WillCascadeOnDelete(false);
我以为这样:每个国家都需要一种货币。而这种货币可能有零个,一个或多个国家分配(可选)。每当我删除货币时,相应的国家(如果有的话)将不会被级联删除。
令人惊讶的是,如果我删除相应的货币。任何人都可以告诉我我想念什么?
首先,您将货币指定为国家/地区的必填字段,因此您可以不要删除货币。您需要删除[必需]。
其次,您的模型构建器需要以下内容:
modelBuilder.Entity< Country>()
.HasRequired(cou => cou.Currency)//注意可选,不需要
.WithMany(c => c.Countries)//定义关系
.WillCascadeOnDelete(false);
第三,您需要从其子节点中明确删除对要删除的实体的引用: p>
货币c = context.Currencies.FirstOrDefault();
c.Countries.Clear(); //这些删除子对象和父对象之间的链接
context.Currencies.Remove(c);
context.SaveChanges();
因为我怀疑翻译中有丢失的东西找到完整的代码演示了无级联删除是否正常工作。
public class国家{
[Key]
public Guid ID {get;组; }
public virtual货币货币{get;组; }
}
public class Currency {
[Key]
public Guid ID {get;组; }
public virtual ICollection< Country>国家{get;组; }
}
public class MyContext:DbContext {
public DbSet< Currency>货币{get;组; }
public DbSet< Country>国家{get;组;
protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Entity< Country>()
.HasRequired(country => country.Currency)
。 WithMany(currency => currency.Countries)
.WillCascadeOnDelete(false);
}
}
类程序{
static void Main(string [] args){
Database.DefaultConnectionFactory = new SqlCeConnectionFactory(System.Data .SqlServerCe.4.0\" );
Database.SetInitializer(new DropCreateDatabaseAlways< MyContext>());
using(MyContext context1 = new MyContext()){
Currency c = new Currency {ID = Guid.NewGuid()};
context1.Currencies.Add(c);
c.Countries = new List< Country>();
c.Countries.Add(new Country {ID = Guid.NewGuid()});
context1.SaveChanges();
}
using(MyContext context2 = new MyContext()){
Currency c = context2.Currencies.FirstOrDefault();
context2.Currencies.Remove(c);
//由于外键约束引发异常
//无法删除主键值
//因为对该键的引用仍然存在。
// [外键约束名称= Country_Currency]
context2.SaveChanges();
}
}
}
您将收到错误保存,因为您删除的东西是必需的外键。
I have to admit, the features of EF 4.1 RC Codefirst, DataAnnotations and FluentAPI are still overwhelming to me. Sometimes I really don't know what I am doing ;-) Please see the following POCOs:
public class Country
{
[Key]
public Guid ID { get; set; }
[Required]
public virtual Currency Currency { get; set; }
}
public class Currency
{
[Key]
public Guid ID { get; set; }
public virtual ICollection<Country> Countries { get; set; }
}
The general idea: Every country needs to have a currency. But a currency does not need to be assigned to a country at all.
If you let EF create the corresponding database, the relationship will be set to CASCADE DELETE by convention. In other words: if you delete a currency, the corresponding countries are deleted as well. But in my case this is not what I want.
I came up with some code in FluentAPI in order to disable CASCADE DELETE:
modelBuilder.Entity<Country>()
.HasRequired(cou => cou.Currency)
.WithOptional()
.WillCascadeOnDelete(false);
I thought this means: Every country requires a currency. And this currency might have zero, one or more countries assigned (optional). And whenever I delete a currency, the corresponding countries (if there are any) will NOT be cascade deleted.
Surprisingly the given approach will still cascade delete a country if I delete the corresponding currency. Can anybody tell me what I miss?
Firstly you've specified the currency as a required field on country, so you can't delete a currency. You'll need to remove the [Required].
Secondly, your model builder need the following:
modelBuilder.Entity<Country>()
.HasRequired(cou => cou.Currency) //note optional, not required
.WithMany(c=>c.Countries) //define the relationship
.WillCascadeOnDelete(false);
Thirdly, you need to explicitly remove the reference to the entity you are deleting from it's children:
Currency c = context.Currencies.FirstOrDefault();
c.Countries.Clear(); //these removes the link between child and parent
context.Currencies.Remove(c);
context.SaveChanges();
[EDIT]Because I suspect there is something lost in translation find the complete code that demonstrates how no-cascading deletes would work.
public class Country{
[Key]
public Guid ID { get; set; }
public virtual Currency Currency { get; set; }
}
public class Currency{
[Key]
public Guid ID { get; set; }
public virtual ICollection<Country> Countries { get; set; }
}
public class MyContext : DbContext{
public DbSet<Currency> Currencies { get; set; }
public DbSet<Country> Countries { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Entity<Country>()
.HasRequired(country => country.Currency)
.WithMany(currency => currency.Countries)
.WillCascadeOnDelete(false);
}
}
class Program{
static void Main(string[] args){
Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
using (MyContext context1 = new MyContext()){
Currency c = new Currency{ID = Guid.NewGuid()};
context1.Currencies.Add(c);
c.Countries = new List<Country>();
c.Countries.Add(new Country{ID = Guid.NewGuid()});
context1.SaveChanges();
}
using (MyContext context2 = new MyContext()){
Currency c = context2.Currencies.FirstOrDefault();
context2.Currencies.Remove(c);
//throws exception due to foreign key constraint
//The primary key value cannot be deleted
//because references to this key still exist.
//[ Foreign key constraint name = Country_Currency ]
context2.SaveChanges();
}
}
}
You will get an error on saving, because your deleting something that is a required foreign key.
这篇关于EF 4.1 RC:奇怪的级联删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!