Как добавить внешний ключ в таблицу клиентов (столбец CreatedBy) для таблицы AspNetUser (столбец Id) в ASP.NET MVC 5 Identity 2.0 с использованием Code First

Я создал проект Empty MVC (веб-приложение ASP.NET), используя Visual Studio 2013 Update 2 RC, а затем добавил образцы удостоверений AspNet, используя:

PM> Установить-пакет Microsoft.AspNet.Identity.Samples -Pre

Я включил и добавил миграции, а затем обновил базу данных, в которой были созданы таблицы по умолчанию. введите описание изображения здесь

Я хочу создать таблицу клиентов, содержащую 2 столбца в качестве внешних ключей, чтобы:

  • Таблица групп (столбец GroupId)
  • Таблица AspNetUsers (столбец Id)

Итак, я создал 2 класса Customer и Group и добавил внешние ключи, используя аннотации данных, как показано ниже:

namespace IdentitySample.Models
{
    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
    public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        static ApplicationDbContext()
        {
            // Set the database intializer which is run once during application start
            // This seeds the database with admin user credentials and admin role
            Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Group> Groups { get; set; }
    }

    public class Customer
    {
        public int CustomerId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public int GroupId { get; set; }
        public string CreatedBy { get; set; }



        [ForeignKey("GroupId")]
        public Group Groups { get; set; }

        [ForeignKey("CreatedBy")]
        public ApplicationUser ApplicationUsers { get; set; }
    }

    public class Group
    {
        public int GroupId { get; set; }
        public string GroupName { get; set; }
    }
}

Кажется, все в порядке, диаграмма ApplicationDbContext.edmx, созданная с помощью инструментов EF Power, также выглядит нормально, и проект строится правильно.

введите описание изображения здесь

Затем я добавил CustomersController, используя шаблон построения «Контроллер MVC 5 с представлениями, использующий Entity Framework».

введите описание изображения здесь

Теперь я получаю ошибку компиляции (в db.ApplicationUsers)

// GET: Customers/Create
public ActionResult Create()
{
    ViewBag.CreatedBy = new SelectList(db.ApplicationUsers, "Id", "Email");
    ViewBag.GroupId = new SelectList(db.Groups, "GroupId", "GroupName");
    return View();
}

введите описание изображения здесь

Сведения об ошибке: IdentitySample.Models.ApplicationDbContext не содержит определения для ApplicationUsers, и не может быть найден метод расширения ApplicationUsers, принимающий первый аргумент типа IdentitySample.Models.ApplicationDbContext (если вам не хватает директиву using или ссылку на сборку?)

Когда я добавляю код ниже в ApplicationDbContext

public DbSet<ApplicationUser> ApplicationUsers { get; set; }

Я получаю ошибку:

Несколько наборов объектов для одного типа не поддерживаются. Наборы объектов ApplicationUsers и Users могут содержать экземпляры типа IdentitySample.Models.ApplicationUser.

Я хочу добавить CreatedBy в качестве внешнего ключа к AspNetUsers, с помощью которого шаблон генерирует раскрывающийся список CreatedBy, аналогичный раскрывающемуся списку GroupId:

введите описание изображения здесь

Как мы можем использовать таблицы, сгенерированные идентификатором, с другими таблицами, созданными пользователем, если таблица, созданная пользователем, имеет ссылки внешнего ключа на таблицы, созданные с помощью идентификатора. И у вас есть первоклассный опыт генерации кода каркаса с использованием «Контроллера MVC 5 с представлениями, использующего Entity Framework»?
(Подобно тому, что у нас есть с таблицей Customers & Groups, где в таблице Customers есть GroupId Foreign ключевая ссылка)


person user3542245    schedule 16.04.2014    source источник


Ответы (2)


RTFE: у вас нет свойства ApplicationUsers в вашем ApplicationDbContext классе.

Просто добавь:

    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
person Rudi    schedule 17.04.2014
comment
Я тоже пробовал добавить это, но во время RunTime получаю ошибку: Multiple object sets per type are not supported. The object sets 'ApplicationUsers' and 'Users' can both contain instances of type 'IdentitySample.Models.ApplicationUser'. - person user3542245; 17.04.2014
comment
Ах, в этом случае вам нужно использовать ViewBag.CreatedBy = new SelectList(db.Users, "Id", "Email"); для получения пользователей. - person Rudi; 17.04.2014
comment
Большое спасибо, это работает. Однако есть ли способ, при котором код шаблона формирования шаблонов CustomersController добавляет db.Users по умолчанию вместо того, чтобы мы изменяли db.ApplicationUsers вручную? - person user3542245; 17.04.2014
comment
Руди, ApplicationUsers этого не должно быть, он уже использует DBContext под ASP.NET Identity ... - person dima; 17.04.2014
comment
Это правильный ответ? Зачем это отмечать ... Я считаю, что это неправильно. Как говорит @dima - person MichaelMao; 30.04.2016
comment
Это неверно, это не должно быть правильным ответом, ответ @dima правильный. - person Dush; 24.09.2018

Entity Framework достаточно умен, чтобы распознавать обычное имя для идентификаторов / ключей. Итак, чтобы добавить внешний ключ, вы должны сделать это:

public class Customer
{
    public string CustomerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public int ApplicationUserId { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; } 
}

По соглашению он соответствует имени класса плюс «Id» в качестве внешнего ключа. Если вы не хотите использовать это соглашение, вы можете использовать аннотацию данных ForeignKey, чтобы помочь EF понять, каким должен быть внешний ключ:

public class Customer
{
    public string CustomerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public int UserId { get; set; }
    [ForeignKey("UserId")]
    public ApplicationUser ApplicationUser { get; set; }
}

Взгляните на this и this для получения дополнительной информации.

person dima    schedule 16.04.2014
comment
Я попытался добавить UserId, как указано выше, но все равно получаю ошибку. Я добавил изображения и групповой класс, чтобы более подробно объяснить свой вопрос. - person user3542245; 17.04.2014
comment
подождите, а вопрос был о правильном способе добавления внешних ключей, теперь вы изменили вопрос? Это не так, как должно работать. Вам следовало закрыть исходный вопрос и задать еще один. Теперь вы хотите сделать что-то совершенно отличное от того, о чем вы изначально просили, и мой ответ становится неактуальным для тех, кто действительно ищет правильный способ добавить внешний ключ. - person dima; 17.04.2014
comment
Что касается вашего нового вопроса, он повсюду, вы пытаетесь сделать несколько вещей одновременно и задать несколько вопросов ... вам нужно сосредоточиться на одном, а затем перейти к другому ... как вы пытался определить ApplicationUsers и Groups в вашем Customer классе отношения один-к-одному, но вы хотите создать для них раскрывающийся список ... во-вторых, когда вы строите объект Customer, а затем по какой-то причине вы хотите создать выпадайте для ApplicationUser, что я действительно не понимаю, чего вы пытаетесь достичь, делая это, и в-третьих, CreatedBy - это строка - person dima; 17.04.2014
comment
С помощью предоставленной вами информации и ссылки вместе с комментарием Руди я могу создать внешний ключ в таблице клиентов и заполнить UserIds в раскрывающемся списке, созданном шаблоном по умолчанию. - person user3542245; 18.04.2014
comment
Этот ответ на самом деле решил для меня очень похожую проблему. Пытался добавить ApplicationUser в качестве внешнего ключа, но он не работал. Добавлен атрибут [ForeignKey ()], указывающий на фактический внешний ключ, который я хотел использовать, и готово! Работал. Спасибо. - person Eric; 22.10.2014