Reputation: 4339
I have an object in my domain model, User
which contains a List of configuration settings. It looks like this:
public class User
{
public int ID { get; set; }
/* various user properties */
public List<ConfigurationSetting> Settings { get; set; }
}
The Configuration Setting has the following definition:
public class ConfigurationSetting
{
public int ID { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public MasterAccount Account { get; set; }
}
As you can see, there is no inverse navigation property in the configuration class. This is because settings are attached to a MasterAccount
and optionally applied to a User
, hence the need for a mapping table.
I am trying to create the relationship in my configuration UserConfiguration
as follows:
HasMany(x => x.Settings)
.WithMany()
.Map(m =>
{
m.ToTable("MapUserSettings");
m.MapLeftKey("UserId");
m.MapRightKey("SettingId");
});
Note that the ID's are renamed using the following:
HasKey(x => x.ID);
Property(x => x.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.HasColumnName("UserId");
When EF Code First attempts to create the model I get the following:
'FK_dbo.MapUserSettings_dbo.Settings_SettingId' on table 'MapUserSettings' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
How can I correctly configure cascading?
Upvotes: 1
Views: 267
Reputation: 12879
I've tried to reproduce your problem given the information you've provided, and I can't get EF to complain about building the model.
The one thing you didn't provide was a definition for MasterAccount
, so I have to believe that you have some relationship coded there that is causing the circular dependency.
If the issue is simply that you don't want cascading delete for one/all of the relationships, you can disable it using the Fluent API by adding
.WillCascadeOnDelete(false)
to the relationship's configuration. For example:
modelBuilder.Entity<User>()
.HasMany(x => x.Settings)
.WithRequired()
.WillCascadeOnDelete(false)
Below is what I coded up that works fine in my environment:
public class User
{
public int ID { get; set; }
/* various user properties */
public List<ConfigurationSetting> Settings { get; set; }
}
public class ConfigurationSetting
{
public int ID { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public MasterAccount Account { get; set; }
}
public class MasterAccount
{
public int ID { get; set; }
public List<ConfigurationSetting> Settings { get; set; }
public User User { get; set; }
}
public class MyContext : DbContext
{
public DbSet<MasterAccount> MasterAccounts { get; set; }
public DbSet<ConfigurationSetting> Settings { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasKey(x => x.ID);
modelBuilder.Entity<User>()
.Property(x => x.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.HasColumnName("UserId");
modelBuilder.Entity<User>()
.HasMany(x => x.Settings)
.WithMany()
.Map(m =>
{
m.ToTable("MapUserSettings");
m.MapLeftKey("UserId");
m.MapRightKey("SettingId");
});
base.OnModelCreating(modelBuilder);
}
}
Upvotes: 2