简体   繁体   English

与Fluent API(现有数据库)的多对多关系

[英]Many to Many relationship with Fluent API (existing database)

My application will have Users and Groups. 我的应用程序将具有用户和组。 A User can be a part of more than one Group . 一个User可以是多个Group的一部分。 A Group can also have more than one User . 一个Group也可以有多个User

I have been using this as a reference. 我一直以此为参考。 In particular, the part near the bottom labeled "Many Relationship". 特别是,靠近底部的部分标记为“许多关系”。 The difference between that example and my project is that my table already exists and I need to map my models to it. 该示例与我的项目之间的区别在于,我的表已经存在,并且需要将我的模型映射到该表。 I suspect I should be able to remove my primary key from the Membership table and it might work (since it closer matches the example), but I would like to make sure before I mess with the database tables. 我怀疑我应该能够从Membership表中删除我的主键,并且它可能起作用(因为它与示例更接近),但是我想确保在弄乱数据库表之前。 It's also very likely that my Fluent is totally wrong. 我的Fluent也很可能是完全错误的。

EDIT 编辑

As I am further researching the answer to this question, I stumbled upon a few things that may enhance the quality of the answers provided. 在我进一步研究该问题的答案时,我偶然发现了一些可以提高所提供答案质量的东西。 I want to note that it is required to be able to add a User , Usergroup , and Membership independently. 我想指出,需要能够独立添加UserUsergroupMembership

SQL 的SQL

CREATE TABLE TestDB.[UserGroup]
(
    GroupID int identity not null,
    Name varchar(100) not null,
    Comment varchar(1000)

    PRIMARY KEY(GroupID)
)
CREATE TABLE TestDB.[User]
(
    SomeID int not null,
    FirstName varchar(100) not null,
    LastName varchar(100) not null,
    Middle varchar(1) not null,
    Email varchar(100) not null,
    Phone varchar(16) not null,
    Comment varchar(1000)

    PRIMARY KEY(SomeID)
)
CREATE TABLE TestDB.[Membership]
(
    MembershipID int identity not null,
    GroupID int not null,
    SomeID int not null

    PRIMARY KEY(MembershipID)
    FOREIGN KEY(GroupID) references TestDB.[UserGroup](GroupID),
    FOREIGN KEY(SomeID) references TestDB.[User](SomeID)
)

NOTE: SomeID is named as such because the ID is given via another system. 注意: SomeID之所以这样命名,是因为该ID是通过另一个系统给出的。 The database will not automatically generate this particular ID. 数据库将不会自动生成此特定ID。 It is guaranteed to be unique. 保证是唯一的。

Model 模型

public class UserGroup
{ 
    public int GroupID { set; get; }
    public string Name { set; get; }
    public string Comment { set; get; }

    public virtual ICollection<User> Users { set; get; }
}
public class User
{
    public string SomeID { set; get; }
    public string FirstName { set; get; }
    public string LastName { set; get; }
    public string Email { set; get; }
    public string Phone { set; get; }
    public string Comment { set; get; }

    public virtual ICollection<UserGroup> UserGroups { set; get; }
}

Fluent Mapping 流利的映射

modelBuilder.Entity<User>().ToTable("User", "TestDB");
modelBuilder.Entity<User>().HasKey(r => new { r.SomeID });
modelBuilder.Entity<User>()
            .HasMany(r => r.UserGroups)
            .WithMany(r => r.Users)
            .Map(m =>
                {
                    m.MapLeftKey("SomeID");
                    m.MapRightKey("GroupID");
                    m.ToTable("Membership");
                });

modelBuilder.Entity<UserGroup>().ToTable("UserGroup", "TestDB");
modelBuilder.Entity<UserGroup>().HasKey(r => new { r.GroupID });

Current Issue Code has been updated to reflect what I currently have. 当前问题代码已更新,以反映我当前的情况。 I am able to query both Users and UserGroups independently, but it will not allow me to access the Navigation Properties . 我能够查询两个UsersUserGroups独立,但它不会让我访问Navigation Properties

I figured it out. 我想到了。 My initial issues were quite silly and I was a lot closer than I had thought. 我最初的问题很傻,而且比我想象的要亲密得多。 One of those silly mistakes was actually mapping two entities to the same table which broke every call to that database. 这些愚蠢的错误之一是实际上将两个实体映射到同一张表,这中断了对该数据库的每次调用。

The first thing you need to do is make sure all your Navigation properties are virtual. 您需要做的第一件事是确保所有“ Navigation properties都是虚拟的。

public virtual ICollection<User> Users { set; get; }

From here you need to figure out the Fluent API mapping. 从这里您需要弄清楚Fluent API映射。 I had initially forgotten to include the schema for ToTable , which was not allowing me to traverse from User to UserGroup . 最初我忘记包括ToTable的架构,这不允许我从User遍历到UserGroup In an instance where you are not working on an existing database, the .Map block would not be required. 如果您不在现有数据库上工作,则不需要.Map块。 A table would be generated automatically containing Keys SomeID and GroupID . 将自动生成一个包含密钥SomeIDGroupID The table name will be the result of the two child table names concatenated. 该表名将是两个子表名串联在一起的结果。 Read more here . 在这里阅读更多。 When working with an existing database, this will simply map that table it would have created to one you already did. 使用现有数据库时,这只会将其创建的表映射到您已经创建的表。

modelBuilder.Entity<User>()
        .HasMany(r => r.UserGroups)
        .WithMany(r => r.Users)
        .Map(m =>
            {
                m.MapLeftKey("SomeID");
                m.MapRightKey("GroupID");
                m.ToTable("Membership", "TempDB");
            });

Another Great Source 另一个伟大的来源

You dont need or want to have users in groups and groups in users. 您不需要或不想将用户分为组和用户组。 You should pick one or the other. 您应该选择一个。 IMHO I would drop List <user> from UserGroups object. 恕我直言,我将从UserGroups对象中删除List <user>

A collection of User objects can still be queried with Linq to generate a list of users who belong to a specific group. 仍然可以使用Linq查询User对象的集合,以生成属于特定组的用户列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM