Идентификация ASP.NET с базой данных EF First MVC5

Можно ли использовать новую идентификацию Asp.net с Database First и EDMX? Или сначала только с кодом?

Вот что я сделал:

1) Я создал новый проект MVC5, и новый идентификатор создал новые таблицы пользователей и ролей в моей базе данных.

2) Затем я открыл свой EDMX-файл Database First и перетащил в новую таблицу Identity Users, поскольку у меня есть другие таблицы, которые к ней относятся.

3) После сохранения EDMX генератор POCO Database First автоматически создаст класс User. Однако UserManager и RoleManager ожидают, что класс User наследуется от нового пространства имен Identity (Microsoft.AspNet.Identity.IUser), поэтому использование класса POCO User не будет работать.

Я предполагаю, что возможное решение - отредактировать мои классы генерации POCO, чтобы мой класс User унаследовал от IUser?

Или ASP.NET Identity совместим только с Code First Design?

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Обновление: следуя предложению Андерса Абеля ниже, я сделал это именно так. Это работает, но мне интересно, есть ли более элегантное решение.

1) Я расширил свой класс User объекта, создав частичный класс в том же пространстве имен, что и мои автоматически сгенерированные объекты.

namespace MVC5.DBFirst.Entity
{
    public partial class AspNetUser : IdentityUser
    {
    }
}

2) Я изменил свой DataContext на наследование от IdentityDBContext вместо DBContext. Обратите внимание, что каждый раз, когда вы обновляете свой EDMX и повторно создаете классы DBContext и Entity, вам придется вернуть это значение.

 public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser>  //DbContext

3) Внутри вашего автоматически сгенерированного класса сущности User вы должны добавить ключевое слово override в следующие 4 поля или закомментировать эти поля, поскольку они унаследованы от IdentityUser (шаг 1). Обратите внимание, что каждый раз, когда вы обновляете свой EDMX и повторно создаете классы DBContext и Entity, вам придется вернуть это значение.

    override public string Id { get; set; }
    override public string UserName { get; set; }
    override public string PasswordHash { get; set; }
    override public string SecurityStamp { get; set; }

person Patrick Tran    schedule 12.11.2013    source источник
comment
Вы добавили таблицу AspNetUser в свой EDMX? Кроме того, убедитесь, что ваш AccountController использует MVC5Test_DBEntities (или другое название вашего контекста БД), а не ApplicationContext.   -  person Tim    schedule 15.11.2013
comment
да, я сделал для обоих выше.   -  person Patrick Tran    schedule 04.12.2013
comment
Привет, Патрик, я боролся с этим, и мне было интересно, нашли ли вы рабочее решение?   -  person Tim    schedule 04.12.2013
comment
Рад знать, что я НЕ единственный, у кого есть эта проблема. Я тоже прибегал к аналогичному решению. Менее чем в идеале ... но это работает.   -  person KevDevMan    schedule 12.02.2014
comment
ASP.NET Identity - это дымящаяся куча ____. Ужасная поддержка для базы данных в первую очередь, отсутствие документации, плохие ссылочные ограничения (отсутствует ON CASCADE DELETE на SQL-сервере) и используются строки для идентификаторов (проблемы с производительностью и фрагментация индекса). И это их 297-я попытка создать фреймворк идентичности ...   -  person MrLane    schedule 09.03.2014
comment
@ DeepSpace101 Identity поддерживает DB-first так же, как Code-first. Шаблоны настроены так, чтобы сначала выполнять код, поэтому, если вы начнете с шаблона, вам придется кое-что изменить. Каскадное удаление работает нормально, вы можете легко изменить строки на целые числа. Смотрите мой ответ ниже.   -  person DeepSpace101    schedule 06.06.2014
comment
@ Обувь. Должен сказать, что, возможно, ты ошибаешься. Мне еще предстоит найти рабочий, исчерпывающий пример / учебник о том, как реализовать это в db-first (без документации). API пытается ссылаться на соединительную таблицу IdentityUserRoles через свойство IdentityUser.Roles, которое разрывает связь в EF db-first, поскольку соединительные таблицы не отображаются как сущности (плохие ссылочные ограничения). Я не согласен со строками для идентификаторов, поскольку их можно настроить, указав параметры типа в унаследованных классах. Подводя итог, мне кажется, что они вообще не думали о БД.   -  person James Sampica    schedule 22.08.2014
comment
@Lopsided Я использую dbfirst с mvc5 уже 2 года. Извините, у вас не получается, но это возможно без особых усилий   -  person Lopsided    schedule 17.07.2016
comment
Спасибо. Мне придется попробовать и доложить, если это сработает.   -  person James Sampica    schedule 18.07.2016


Ответы (9)


Должно быть возможно использовать систему идентификации с POCO и Database First, но вам нужно будет сделать пару настроек:

  1. Сделайте частичную реализацию класса User в другом файле
  2. Мои шаги очень похожи, но я хотел поделиться.

Это заставит класс User реализовать правильный интерфейс, не касаясь фактических сгенерированных файлов (редактирование сгенерированных файлов всегда плохая идея).

partial User : IUser
{
}

Обновите .tt-файл для генерации POCO, чтобы классы сущностей были partial. Это позволит вам предоставить дополнительную реализацию в отдельном файле.

person Anders Abel    schedule 12.11.2013
comment
Я пробовал то, что вы упомянули. См. Мой пост для получения обновленной информации ... но решение было не очень элегантным: / - person Patrick Tran; 13.11.2013
comment
У меня была такая же проблема. Кажется, что документация по DB-first очень скудна. Это хорошее предложение, но я думаю, что вы правы, это не совсем работает - person Patrick Tran; 13.11.2013
comment
Есть ли еще какое-нибудь решение, кроме взлома? - person Phil; 06.12.2013
comment
Я использую Onion Architecture, и все POCO находятся в Core. Там не рекомендуется использовать IUser. Есть ли другое решение? - person user20358; 08.04.2014
comment
это решило проблему, я не мог видеть пользователя приложения в базе данных, но после замены соединения по умолчанию все заработало. - person Usman Khalid; 15.06.2015

1) Создайте новый проект MVC5

2) Создайте новый Model.edmx. Даже если это новая база данных и в ней нет таблиц.

3) Отредактируйте web.config и замените сгенерированную строку подключения:

с этой строкой подключения:

<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-SSFInventory-20140521115734.mdf;Initial Catalog=aspnet-SSFInventory-20140521115734;Integrated Security=True" providerName="System.Data.SqlClient" />

После этого соберите и запустите приложение. Зарегистрируйте пользователя, и тогда таблицы будут созданы.

<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />

РЕДАКТИРОВАТЬ: ASP.NET Identity with EF Database First для шаблона проекта MVC5 CodePlex.

person JoshYates1980    schedule 21.05.2014
comment
Проблема не в DBContext, а в том, что UserManager и RoleManager ожидают класса, наследуемого от Microsoft.AspNet.Identity.EntityFramework.IdentityUser - person Hassen Ch.; 16.08.2014

Я хотел использовать существующую базу данных и установить отношения с ApplicationUser. Вот как я сделал это с помощью SQL Server, но та же идея, вероятно, будет работать с любой БД.


Изменить: Схема классов идентичности Asp.Net введите описание изображения здесь

  1. Откройте БД, указанную в DefaultConnection в Web.config. Он будет называться (aspnet- [timestamp] или что-то в этом роде.)
  2. Создайте сценарий для таблиц базы данных.
  3. Вставьте таблицы со сценарием в существующую базу данных в SQL Server Management Studio.
  4. Настройте и добавьте отношения к ApplicationUser (при необходимости).
  5. Создайте новый веб-проект> MVC> Первый проект БД> Импортировать БД с EF ... Исключая вставленные вами классы идентификации.
  6. В IdentityModels.cs измените ApplicationDbContext :base("DefaltConnection"), чтобы использовать DbContext вашего проекта.
  7. :base("DefaltConnection") здесь бесполезен, потому что это объект с первым кодом, используемый _2_ для аутентификации. После определения моего собственного объекта _3_ я реализовал частичный класс, реализующий _4_, который используется классом _5_. Я хотел, чтобы мои _6_ были _7_ вместо строки, поэтому я просто возвращаю идентификатор пользователя toString (). Точно так же я хотел, чтобы _8_ из _9_ был некапитализирован.

Создать проект MVC

person stink    schedule 12.11.2013
comment
открытый класс IdentityDbContext ‹TUser›: DbContext, где TUser: Microsoft.AspNet.Identity.EntityFramework.IdentityUser. При первом использовании базы данных сгенерированные классы сущностей не наследуются ни от каких базовых классов. - person Patrick Tran; 13.11.2013
comment
Затем просто исключите их из базы данных при создании классов с помощью структуры сущностей. - person Patrick Tran; 13.11.2013
comment
Если вы исключите таблицы идентификаторов из EDMX, вы потеряете свойства навигации в других классах, у которых есть внешние ключи для вашего UserID. - person stink; 13.11.2013
comment
Вы в этом разобрались? Почему вы не хотите сначала переходить на код? - person Patrick Tran; 15.11.2013
comment
Я не против сначала перейти к коду ... Просто в некоторых сценариях и компаниях базовые таблицы создает администратор базы данных, а не кодировщик. - person stink; 15.11.2013
comment
@PatrickTran Я знаю, что сообщение устарело, вы можете унаследовать свой dbcontext от identityDbContext ‹T›, и тогда у вас будет весь необходимый доступ к этим полям. - person Patrick Tran; 16.11.2013
comment
Недавно у меня была возможность реализовать это, и по какой-то причине (я полагаю, из-за обновления идентичности 3.0) я не смог реализовать вход в систему, унаследовав IdentityUser, а затем переопределив свойства; но написание настраиваемого UserStore и наследование IUser работали нормально; Просто даю обновление, может, кому-то это пригодится. - person Ken; 17.08.2019

Вам ни в коем случае не нужно IUser. Это всего лишь интерфейс, используемый UserManager. Поэтому, если вы хотите определить другой «IUser», вам придется переписать этот класс, чтобы использовать свою собственную реализацию.

public partial class User : IUser
{

    public string Id
    {
        get { return this.UserID.ToString(); }
    }

    public string UserName
    {
        get
        {
            return this.Username;
        }
        set
        {
            this.Username = value;
        }
    }
}

Теперь вы пишете свой собственный UserStore, который обрабатывает все хранилища пользователей, утверждений, ролей и т. Д. Реализуйте интерфейсы всего, что делает UserStore сначала код, и измените where TUser : IdentityUser на where TUser : User, где «Пользователь» - это ваш объект сущности.

public class UserManager<TUser> : IDisposable where TUser: IUser

Вот пара примеров некоторых реализаций интерфейса.

public class MyUserStore<TUser> : IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserRoleStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserStore<TUser>, IDisposable where TUser : User
{
    private readonly MyAppEntities _context;
    public MyUserStore(MyAppEntities dbContext)
    { 
        _context = dbContext; 
    }

    //Interface definitions
}

Используя шаблон MVC 5, я изменил AccountController, чтобы он выглядел так.

async Task IUserStore<TUser>.CreateAsync(TUser user)
{
    user.CreatedDate = DateTime.Now;
    _context.Users.Add(user);
    await _context.SaveChangesAsync();
}

async Task IUserStore<TUser>.DeleteAsync(TUser user)
{
    _context.Users.Remove(user);
    await _context.SaveChangesAsync();
}

Теперь вход в систему должен работать с вашими собственными таблицами.

public AccountController()
        : this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}

Взгляните на этот проект на GitHub: https://github.com/KriaSoft/AspNet.Identity

person James Sampica    schedule 14.01.2014
comment
Можете дать ссылку на всю реализацию интерфейса или на весь проект? - person Naz Ekin; 10.08.2015
comment
есть ли конкретная причина, по которой вы использовали здесь частичный класс? - person DespeiL; 11.04.2016
comment
Если вы используете edmx для создания своих моделей, вы должны использовать частичный класс. Если вы сначала пишете код, вы можете опустить это - person user8964654; 16.12.2019
comment
Я дважды перепробовал все, что вы упомянули в своем блоге, у меня не получилось. - person James Sampica; 16.12.2019

Который включает в себя:

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

  • Entity Framework Database-First Provider (-ы)
  • Исходный код и образцы
  • Хороший вопрос.

См. также: Как создать поставщик Database-First для ADO.NET Identity

Шаблон проекта базы данных SQL для ASP.NET Identity 2.0

person Konstantin Tarkus    schedule 13.04.2014

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

Я хотел настроить схему идентификации aspnet и не беспокоиться о миграции. Я хорошо разбираюсь в проектах баз данных Visual Studio (sqlpackage, data-dude) и знаю, как они неплохо справляются с обновлением схем.

Мое упрощенное решение:

1) Создайте проект базы данных, который отражает схему идентификации aspnet 2) используйте выходные данные этого проекта (.dacpac) в качестве ресурса проекта 3) разверните .dacpac при необходимости

Для MVC5 изменение класса ApplicationDbContext, похоже, помогает ...

1) Реализуйте IDatabaseInitializer

2) В конструкторе сигнализируйте, что этот класс будет реализовывать инициализацию базы данных:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }

3) Реализуйте InitializeDatabase:

Database.SetInitializer<ApplicationDbContext>(this);

Здесь я решил использовать DacFX и развернуть свой .dacpac

Я потратил несколько часов на работу над этим и наконец нашел решение, которым поделился в своем блоге здесь. По сути, вам нужно сделать все, что сказано в ответе stink, но с одной дополнительной вещью: убедиться, что Identity Framework имеет конкретный SQL -Строка подключения клиента поверх строки подключения Entity Framework, используемой для сущностей вашего приложения.

    void IDatabaseInitializer<ApplicationDbContext>.InitializeDatabase(ApplicationDbContext context)
    {
        using (var ms = new MemoryStream(Resources.Binaries.MainSchema))
        {
            using (var package = DacPackage.Load(ms, DacSchemaModelStorageType.Memory))
            {
                DacServices services = new DacServices(Database.Connection.ConnectionString);
                var options = new DacDeployOptions
                {
                    VerifyDeployment = true,
                    BackupDatabaseBeforeChanges = true,
                    BlockOnPossibleDataLoss = false,
                    CreateNewDatabase = false,
                    DropIndexesNotInSource = true,
                    IgnoreComments = true,

                };
                services.Deploy(package, Database.Connection.Database, true, options);
            }
        }
    }
person Aaron Hudon    schedule 17.09.2015

Таким образом, ваше приложение будет использовать строку подключения для Identity Framework, а другую - для сущностей вашего приложения. Каждая строка подключения относится к разному типу. Прочтите мой пост в блоге, чтобы получить полное руководство.

Я обнаружил, что у @ JoshYates1980 есть самый простой ответ.

person Daniel Eagle    schedule 20.05.2014
comment
@Badhon Мне очень жаль, что инструкции в моем блоге не сработали для вас. Бесчисленное количество людей выражали свою благодарность за то, что они добились успеха после моей статьи. Всегда помните, что если Microsoft что-то обновит, это может повлиять на результат. Я написал статью для ASP.NET MVC 5 с Identity Framework 2.0. Все, что выходит за рамки этого, может вызвать проблемы, но до сих пор я получил очень недавние комментарии, указывающие на успех. Я бы хотел узнать больше о вашей проблеме. - person Badhon Jain; 03.11.2015
comment
Я попытаюсь повторить еще раз, проблема, с которой я столкнулся, заключалась в том, что я не мог использовать свою настраиваемую базу данных, она использовала автоматически созданную базу данных. В любом случае, я не хотел сказать что-то не так с вашей статьей. Спасибо, что поделились своими знаниями. - person Daniel Eagle; 06.11.2015
comment
@Badhon Не беспокойся, друг мой, я никогда не чувствовал, что ты говоришь что-то не так со статьей. У всех нас есть уникальные ситуации с различными крайними случаями, поэтому иногда то, что работает для других, не обязательно работает для нас. Надеюсь, вы смогли решить свою проблему. - person Badhon Jain; 09.11.2015
comment

- person Daniel Eagle; 17.12.2015

После серии проб и ошибок я сделал то, что предложил Джош, и заменил connectionString моей сгенерированной строкой подключения к БД. Изначально меня смутил следующий пост:

Как добавить аутентификацию удостоверения ASP.NET MVC5 в существующая база данных

В принятом ответе от @Win указано, что нужно изменить имя соединения ApplicationDbContext(). Это немного расплывчато, если вы сначала используете Entity и подход к базе данных / модели, при котором строка подключения к базе данных создается и добавляется в файл Web.config.

Имя соединения ApplicationDbContext() сопоставлено с соединением по умолчанию в файлеWeb.config. Таким образом, метод Джоша работает лучше всего, но чтобы сделать ApplicationDbContext() более читабельным, я бы предложил изменить имя на имя вашей базы данных, как было изначально опубликовано @Win, не забудьте изменить connectionString для «DefaultConnection» в Web.config и закомментировать и / или удалить сгенерированную Entity базу данных include.

Примеры кода:

У нас есть проект DLL модели сущностей, в котором мы храним наш класс модели. Мы также ведем проект базы данных со всеми скриптами базы данных. Мой подход был следующим

person TheSchnitz    schedule 09.03.2017

1) Создайте свой собственный проект с EDMX, используя сначала базу данных

2) Создайте сценарий для таблиц в своей базе данных, я использовал VS2013, подключенный к localDB (подключения к данным), и скопировал сценарий в проект базы данных, добавьте любые настраиваемые столбцы, например. Дата рождения [DATE] не равно null

3) Разверните базу данных

4) Обновите проект модели (EDMX) Добавить в проект модели

5) Добавьте любые настраиваемые столбцы в класс приложения

В проект MVC AccountController добавлено следующее:

public class ApplicationUser : IdentityUser
{
    public DateTime BirthDate { get; set; }
}

Поставщик удостоверений хочет, чтобы для него работала строка подключения SQL, чтобы сохранить только 1 строку подключения для базы данных, извлечь строку поставщика из строки подключения EF

у вас есть образец кода вашей реализации? поскольку когда я пытаюсь воспроизвести вышеуказанное, я получаю сообщение об ошибке при попытке войти в систему или зарегистрировать пользователя. Тип сущности AspNetUser не является частью модели для текущего контекста, где AspNetUser - это моя сущность пользователя.

public AccountController()
{
   var connection = ConfigurationManager.ConnectionStrings["Entities"];
   var entityConnectionString = new EntityConnectionStringBuilder(connection.ConnectionString);
        UserManager =
            new UserManager<ApplicationUser>(
                new UserStore<ApplicationUser>(
                    new ApplicationDbContext(entityConnectionString.ProviderConnectionString)));
}
person Haroon    schedule 06.04.2014