Programing

EF Database First MVC5를 사용한 ASP.NET ID

lottogame 2020. 9. 12. 11:20
반응형

EF Database First MVC5를 사용한 ASP.NET ID


Database First 및 EDMX와 함께 새로운 Asp.net Identity를 사용할 수 있습니까? 아니면 코드를 먼저 사용합니까?

내가 한 일은 다음과 같습니다.

1) 새 MVC5 프로젝트를 만들고 새 ID로 데이터베이스에 새 사용자 및 역할 테이블을 생성했습니다.

2) 그런 다음 Database First EDMX 파일을 열고 관련된 다른 테이블이 있으므로 새 Identity Users 테이블로 끌어 왔습니다.

3) EDMX를 저장하면 Database First POCO 생성기가 자동으로 User 클래스를 생성합니다. 그러나 UserManager 및 RoleManager는 새 Identity 네임 스페이스 (Microsoft.AspNet.Identity.IUser)에서 상속 된 User 클래스를 예상하므로 POCO User 클래스를 사용할 수 없습니다.

가능한 해결책은 내 사용자 클래스가 IUser에서 상속되도록 POCO 생성 클래스를 편집하는 것입니다.

아니면 ASP.NET Identity는 Code First Design 과만 호환됩니까?

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

업데이트 : 아래의 Anders Abel의 제안에 따라 이것이 제가 한 일입니다. 작동하지만 더 우아한 솔루션이 있는지 궁금합니다.

1) 자동 생성 엔터티와 동일한 네임 스페이스 내에 부분 클래스를 만들어 엔터티 User 클래스를 확장했습니다.

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

2) DBContext 대신 IdentityDBContext에서 상속하도록 DataContext를 변경했습니다. EDMX를 업데이트하고 DBContext 및 Entity 클래스를 다시 생성 할 때마다이 값을 다시 설정해야합니다.

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

3) 자동 생성 된 User 엔터티 클래스 내에서 다음 4 개 필드에 override 키워드를 추가하거나 이러한 필드가 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; }

POCO 및 Database First와 함께 ID 시스템을 사용할 수 있어야하지만 몇 가지 조정이 필요합니다.

  1. 엔티티 클래스를 만들기 위해 POCO 생성 용 .tt 파일을 업데이트합니다 partial. 이렇게하면 별도의 파일에 추가 구현을 제공 할 수 있습니다.
  2. User다른 파일 에서 클래스를 부분적으로 구현 합니다.

 

partial User : IUser
{
}

그러면 User클래스가 실제 생성 된 파일을 건드리지 않고 올바른 인터페이스를 구현 하게됩니다 (생성 된 파일을 편집하는 것은 항상 나쁜 생각입니다).


내 단계는 매우 비슷하지만 공유하고 싶었습니다.

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

그런 다음 애플리케이션을 빌드하고 실행하십시오. 사용자를 등록하면 테이블이 생성됩니다.


편집 : MVC5 CodePlex 프로젝트 템플릿에 대한 EF 데이터베이스 우선 ASP.NET ID.


기존 데이터베이스를 사용하고 ApplicationUser와 관계를 만들고 싶었습니다. 이것은 SQL Server를 사용하여 수행 한 방법이지만 동일한 아이디어가 아마도 모든 DB에서 작동 할 것입니다.

  1. MVC 프로젝트 만들기
  2. Web.config의 DefaultConnection 아래에 나열된 DB를 엽니 다. (aspnet- [timestamp] 또는 이와 유사한 이름으로 호출됩니다.)
  3. 데이터베이스 테이블을 스크립팅합니다.
  4. SQL Server Management Studio의 기존 데이터베이스에 스크립팅 된 테이블을 삽입합니다.
  5. ApplicationUser 에 관계를 사용자 정의하고 추가합니다 (필요한 경우).
  6. 새 웹 프로젝트 생성> MVC> DB 첫 번째 프로젝트> EF를 사용하여 DB 가져 오기 ... 삽입 한 ID 클래스 제외.
  7. 에서 IdentityModels.cs ApplicationDbContext 변경 :base("DefaltConnection")프로젝트의 DbContext를 사용할 수 있습니다.

편집 : Asp.Net 신원 클래스 다이어그램 enter image description here


IdentityUser is worthless here because it's the code-first object used by the UserStore for authentication. After defining my own User object, I implemented a partial class that implements IUser which is used by the UserManager class. I wanted my Ids to be int instead of string so I just return the UserID's toString(). Similarly I wanted n in Username to be uncapitalized.

public partial class User : IUser
{

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

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

You by no means need IUser. It's only an interface used by the UserManager. So if you want to define a different "IUser" you would have to rewrite this class to use your own implementation.

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

You now write your own UserStore which handles all of the storage of users, claims, roles, etc. Implement the interfaces of everything that the code-first UserStore does and change where TUser : IdentityUser to where TUser : User where "User" is your entity object

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
}

Here are a couple examples on some of the interface implementations

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

Using the MVC 5 template, I changed the AccountController to look like this.

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

Now logging in should work with your own tables.


Take a look at this project on GitHub: https://github.com/KriaSoft/AspNet.Identity

Which includes:

  • SQL Database Project Template for ASP.NET Identity 2.0
  • Entity Framework Database-First Provider(s)
  • Source Code and Samples

enter image description here

Also see: How to create Database-First provider for ADO.NET Identity


I spent several hours working through this and finally found a solution which I have shared on my blog here. Basically, you need to do everything said in stink's answer but with one additional thing: ensuring Identity Framework has a specific SQL-Client connection string on top of the Entity Framework connection string used for your application entities.

In summary, your application will use a connection string for Identity Framework and another for your application entities. Each connection string is of a different type. Read my blog post for a full tutorial.


Good question.

I'm more of a database-first person. The code first paradigm seems to loosey-goosey to me, and the "migrations" seem too error prone.

I wanted to customize the aspnet identity schema, and not be bothered with migrations. I'm well versed with Visual Studio database projects (sqlpackage, data-dude) and how it does a pretty good job at upgrading schemas.

My simplistic solution is to:

1) Create a database project that mirrors the aspnet identity schema 2) use the output of this project (.dacpac) as a project resource 3) deploy the .dacpac when needed

For MVC5, modifying the ApplicationDbContext class seems to get this going...

1) Implement IDatabaseInitializer

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

2) In the constructor, signal that this class will implement database initialization:

Database.SetInitializer<ApplicationDbContext>(this);

3) Implement InitializeDatabase:

Here, I chose to use DacFX and deploy my .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);
            }
        }
    }

We have a Entity Model DLL project where we keep our model class. We also keep a Database Project with all of database scripts. My approach was as follows

1) Create your own project that has the EDMX using database first

2) Script the tables in your db, I used VS2013 connected to localDB (Data Connections) and copied the script to database project, add any custom columns, e.g. BirthDate [DATE] not null

3) Deploy the database

4) Update the Model (EDMX) project Add to the Model project

5) Add any custom columns to the application class

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

In the MVC project AccountController added the following:

The Identity Provider want a SQL Connection String for it to work, to keep only 1 connection string for the database, extract the provider string from EF connection string

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

I found that @JoshYates1980 does have the simplest answer.

After a series trials and errors I did what Josh suggested and replaced the connectionString with my generated DB connection string. what I was confused about originally was the following post:

How to add ASP.NET MVC5 Identity Authentication to existing database

Where the accepted answer from @Win stated to change the ApplicationDbContext() connection name. This is a little vague if you are using Entity and a Database/Model first approach where the database connection string is generated and added to the Web.config file.

The ApplicationDbContext() connection name is mapped to the default connection in theWeb.config file. Therefore, Josh's method works best, but to make the ApplicationDbContext() more readable I would suggest changing the name to your database name as @Win originally posted, making sure to change the connectionString for the "DefaultConnection" in the Web.config and comment out and/or remov the Entity generated database include.

Code Examples:

참고URL : https://stackoverflow.com/questions/19940014/asp-net-identity-with-ef-database-first-mvc5

반응형