I have 2 entities with a many-to-many relationship that do not follow code-first naming convention, I have to find a way to override that.
First entity :
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public virtual ICollection<Rule> { get; set; }
}
Second entity :
public class Rule
{
public int RuleId { get; set; }
public string Description { get; set; }
public virtual ICollection<User> { get; set; }
}
I have a table in between of those 2 with the classic mapping (name is UserRule
with a composite primary key made of 2 colums ( UserId, RuleId
) with corresponding foreign keys)
the dbcontext I use is this one :
public class DataContext : DbContext
{
public IDbSet<User> Users { get; private set; }
public IDbSet<Rule> Rules { get; private set; }
private const string ConnectionStringName = "connectionstring";
public DataContext() : base(ConnectionStringName)
{
Configuration.LazyLoadingEnabled = true;
Rules = Set<Rule>();
Users = Set<User>();
}
protected override void OnModelCreating(DbModelBuilder builder)
{
// use this to disable database migrations and not use metadata inside database
Database.SetInitializer<DataContext>(null);
// setup MaestroAgentConfig to its table
builder.Configurations.Add(new UserTable());
// setup SecurityRule to its table
builder.Configurations.Add(new RuleTable());
base.OnModelCreating(builder);
}
public override int SaveChanges()
{
return base.SaveChanges();
}
}
The mapping tables I have are :
public class UserTable : EntityTypeConfiguration<User>
{
public UserProfileTable()
{
Property(x => x.UserId).HasColumnName("UserId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasMany(x => x.SecurityRules)
.WithMany(x => x.UserProfiles)
.Map(map =>
{
map.MapRightKey("UserId");
map.MapRightKey("RuleId");
map.ToTable("UserRule");
});
ToTable("User");
}
}
and :
public class RuleTable : EntityTypeConfiguration<Rule>
{
public RuleTable()
{
Property(x => x.RuleId).HasColumnName("RuleId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasKey(x => x.RuleId);
ToTable("Rule");
}
}
Yet when EF query the DB it looks like this :
exec sp_executesql N'
SELECT TOP (1)
[Extent1].[UserId] AS [UserId],
{ other fields }
FROM
[dbo].[UserProfile] AS [Extent1]
WHERE
[Extent1].[UserName] = @p__linq__0',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'EMYODE\erick.girard'
and :
exec sp_executesql N'
SELECT
[Extent2].[RuleId] AS [RuleId],
[Extent2].[Description] AS [Description]
FROM
[dbo].[UserRule] AS [Extent1]
INNER JOIN
[dbo].[Rule] AS [Extent2] ON [Extent1].[RuleId] = [Extent2].[RuleId]
WHERE
[Extent1].[User_UserId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=37
Now on the 2nd request I can't find a way to use " UserId
" only on the UserRule
table
How can I manage to do this ?
(Edit) I tried removing the following 3 conventions but so far it didn't change anything:
builder.Conventions.Remove<PluralizingEntitySetNameConvention>();
builder.Conventions.Remove<NavigationPropertyNameForeignKeyDiscoveryConvention>();
builder.Conventions.Remove<TypeNameForeignKeyDiscoveryConvention>();
Is your code an exact copy, or pseudo code?
Pasting in your code exactly, I got the same result -
However, you're mapping the right part of the mapping table twice:
map.MapRightKey("UserId");
map.MapRightKey("RuleId");
I changed the top command to map to the left key
map.MapLeftKey("UserId");
map.MapRightKey("RuleId");
and fixed it for me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.