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

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

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

1) Я создал новый проект MVC5 и создал новую Identity для создания новых таблиц User and Roles в моей базе данных.

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

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

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

Или идентификатор ASP.NET совместим только с 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) В рамках автоматически созданного класса сущности пользователя вы должны добавить ключевое слово переопределения в следующие 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; }

Ответ 1

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

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

 

partial User : IUser
{
}

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

Ответ 2

Мои шаги очень похожи, но я хотел поделиться.

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" />

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

Ответ 3

EDIT: Идентификация ASP.NET с базой данных EF Сначала для шаблона проекта MVC5 CodePlex.


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

  • Создайте проект MVC
  • Откройте базу данных, указанную в разделе DefaultConnection в Web.config. Он будет называться (aspnet- [timestamp] или что-то в этом роде.)
  • Script таблицы базы данных.
  • Вставьте скриптовые таблицы в существующую базу данных в SQL Server Management Studio.
  • Настроить и добавить отношения к ApplicationUser (при необходимости).
  • Создать новый веб-проект > MVC > Первый проект DB > Импортировать базу данных с помощью EF... Исключая введенные классы идентификации.
  • В IdentityModels.cs измените ApplicationDbContext :base("DefaltConnection") на использование проекта DbContext.

Изменить: Диаграмма класса идентичности Asp.Net enter image description here

Ответ 4

IdentityUser бесполезен здесь, потому что это первый объект кода, используемый UserStore для аутентификации. После определения моего собственного объекта User я реализовал частичный класс, реализующий IUser, который используется классом UserManager. Я хотел, чтобы мой Id был int вместо строки, поэтому я просто возвращаю UserID toString(). Точно так же я хотел, чтобы n в Username был некапитализирован.

public partial class User : IUser
{

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

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

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

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

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

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
}

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

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();
}

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

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

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

Ответ 6

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

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

Ответ 7

Хороший вопрос.

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

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

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

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

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

1) Внедрить IDatabaseInitializer

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

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

Database.SetInitializer<ApplicationDbContext>(this);

3) Внедрить InitializeDatabase:

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

    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);
            }
        }
    }

Ответ 8

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

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

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

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

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

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

любые настраиваемые столбцы,
public class ApplicationUser : IdentityUser
{
    public DateTime BirthDate { get; set; }
}

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

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

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

Ответ 9

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

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

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

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

Имя соединения ApplicationDbContext() сопоставляется с соединением по умолчанию в файле Web.config. Поэтому метод Josh работает лучше всего, но чтобы сделать ApplicationDbContext() более удобочитаемым, я бы предложил изменить имя на ваше имя базы данных как @Win, изначально опубликованное, убедившись, что вы изменили connectionString для "DefaultConnection" в Web.config и комментарий и/или удаление базы данных, созданной сущностью.

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