I'm trying to design a code-first model with a TPH Lookup Table like the following:
public abstract class LookupValue
{
[Key]
public string Value { get; set; }
}
public class PaymentTerm : LookupValue {}
public class ShippingCode : LookupValue {}
public class ReviewStatus : LookupValue {}
public class RecordStatus : LookupValue {}
I want Entity Framework to generate a table with a discriminator, which it does, as follows;
CREATE TABLE [LookupValues] (
[Value] [nvarchar](30) NOT NULL,
[Discriminator] [nvarchar](128) NOT NULL,
CONSTRAINT [PK_dbo.LookupValues] PRIMARY KEY ([Value])
)
In my context OnModelCreating override, I defined the following:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PaymentTerm>()
.Map(m => m.Requires("Discriminator").HasValue("PaymentTerm"));
modelBuilder.Entity<ShippingCode>()
.Map(m => m.Requires("Discriminator").HasValue("ShippingCode"));
modelBuilder.Entity<ReviewStatus>()
.Map(m => m.Requires("Discriminator").HasValue("ReviewStatus"));
modelBuilder.Entity<RecordStatus>()
.Map(m => m.Requires("Discriminator").HasValue("RecordStatus"));
}
I want to use these lookup objects as follows:
public class Customer {
....
[Required]
public virtual PaymentTerm Terms { get; set; }
[Required]
public virtaul ShippingCode ShippingCode { get; set; }
[Required]
public virtual ReviewStatus ReviewStatus { get; set; }
[Required]
public virtual RecordStatus RecordStatus { get; set; }
...
}
I can create the Code-First Migration, but when I attempt to Update The Database, I get an error
The referential relationship will result in a cyclical reference that is not allowed...
I've figured out that this is due to the ON DELETE CASCADE
that the SQL Script generates as follows:
ALTER TABLE [Customer] ADD CONSTRAINT [FK_dbo.Customer_dbo.LookupValues_ShippingCode_Value] FOREIGN KEY ([ShippingCode_Value]) REFERENCES [LookupValues] ([Value]) ON DELETE CASCADE
ALTER TABLE [Customer] ADD CONSTRAINT [FK_dbo.Customer_dbo.LookupValues_PaymentTerms_Value] FOREIGN KEY ([PaymentTerms_Value]) REFERENCES [LookupValues] ([Value]) ON DELETE CASCADE
ALTER TABLE [CustomerClinicDoctors] ADD CONSTRAINT [FK_dbo.Customer_dbo.LookupValues_RecordStatus_Value] FOREIGN KEY ([RecordStatus_Value]) REFERENCES [LookupValues] ([Value]) ON DELETE CASCADE
ALTER TABLE [Customer] ADD CONSTRAINT [FK_dbo.Customer_dbo.LookupValues_ReviewStatus_Value] FOREIGN KEY ([ReviewStatus_Value]) REFERENCES [LookupValues] ([Value]) ON DELETE CASCADE
I've read that I should put the .WillCascadeOnDelete(false)
in the fluent api, but I can't get it to accept it. Hoping for some help...
How can I turn off the DELETE CASCADE on these relationships. I don't intend do really need the ability to delete the lookup values, but just wanted a simple code interface in my Repository.
You need to define fluent mapping for every relation. Try this:
public class YourContext : DbContext {
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Customer>()
.HasRequired(c => c.Terms)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(c => c.ShippingCode)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(c => c.ReviewStatus)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(c => c.RecordStatus)
.WithMany()
.WillCascadeOnDelete(false);
}
}