我有以下实体类定义:
[Table("Users")]
public class WebUser
{
public virtual int Id { get; set; }
public virtual ICollection<Client> Clients { get; set; }
// more properties...
}
请注意,表名与类名不同。我还有一个ClientUsers
表,它是客户端和用户的多对多映射。问题是,当我尝试访问webUser.Clients
属性时,我得到以下异常:
"Invalid object name 'dbo.ClientWebUsers'."
看起来Entity Framework正在尝试猜测第三个表的名称,但它显然不够聪明,不能考虑我在那里的表属性。如何告诉EF它是ClientUsers
而不是ClientWebUsers
?还有什么规则可以知道哪个表名首先出现,哪个表名在新表名中排在第二位?我认为这不是按字母顺序排列的。
我使用的是EF 5.0。谢谢!
答案 0 :(得分:4)
从您使用Code First的内容来看,我会相应地回答。如果这不正确,请告诉我。
我相信用于确定多对多表的名称的约定由它们在SomeContext:DbContext类中作为DbSet属性出现的顺序决定。
至于强制EntityFramework为您的表命名,您可以在SomeContext:DbContext类的OnModelCreating方法中使用Fluent API,如下所示:
public class DatabaseContext : DbContext
{
public DatabaseContext()
: base("SomeDB")
{
}
public DbSet<WebUser> Users { get; set; }
public DbSet<Client> Clients { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<WebUser>().HasMany(c => c.Clients)
.WithMany(p => p.WebUsers).Map(
m =>
{
m.MapLeftKey("ClientId");
m.MapRightKey("UserId");
m.ToTable("ClientUsers");
});
}
}
这假定您的课程类似于以下内容:
[Table("Users")]
public class WebUser
{
public virtual int Id { get; set; }
public virtual ICollection<Client> Clients { get; set; }
// more properties...
}
public class Client
{
public int Id { get; set; }
public ICollection<WebUser> WebUsers { get; set; }
// more properties
}
最后,这是一个集成测试(NUnit),展示了正常运行的功能。您可能需要在运行之前删除数据库,因为Code First应该更新/迁移/重新创建它。
[TestFixture]
public class Test
{
[Test]
public void UseDB()
{
var db = new DatabaseContext();
db.Users.Add(new WebUser { Clients = new List<Client> { new Client() } });
db.SaveChanges();
var webUser = db.Users.First();
var client = webUser.Clients.FirstOrDefault();
Assert.NotNull(client);
}
}
修改 Link到Fluent API的相关文档
答案 1 :(得分:0)
Rowan的answer(在此处添加以供参考):
以下是有关如何配置多对多表(包括指定表名)的信息。您所追求的代码如下:
modelBuilder.Entity<WebUser>()
.HasMany(u => u.Clients)
.WithMany(c => c.WebUsers)
.Map(m => m.ToTable("ClientUsers");
〜罗文