[asp.net] 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) 자동 생성 된 사용자 엔터티 클래스 내에서 다음 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; }



답변

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 신원 클래스 다이어그램
여기에 이미지 설명 입력


답변

IdentityUserUserStore인증을 위해에서 사용하는 코드 우선 개체이기 때문에 여기서는 쓸모가 없습니다 . 내 자신의 User개체를 정의한 후 클래스에서 IUser사용 하는 부분 클래스를 구현했습니다 UserManager. 나는 문자열 대신에 Ids를 원했기 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. .NET에서 사용하는 유일한 인터페이스 UserManager입니다. 따라서 다른 “IUser”를 정의하려면 자체 구현을 사용하도록이 클래스를 다시 작성해야합니다.

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

당신은 지금 당신의 자신의 쓰기 UserStore코드가 우선하는 것이 모든 것의 인터페이스를 구현하는 등 사용자, 주장, 역할의 저장을 모두 처리하는 UserStore수행하고 변화 where TUser : IdentityUserwhere 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())))
{
}

이제 로그인은 자신의 테이블에서 작동합니다.


답변

GitHub에서이 프로젝트를 살펴보세요 : https://github.com/KriaSoft/AspNet.Identity

다음을 포함합니다.

  • ASP.NET Identity 2.0 용 SQL 데이터베이스 프로젝트 템플릿
  • Entity Framework 데이터베이스 우선 공급자
  • 소스 코드 및 샘플

여기에 이미지 설명 입력

참조 : ADO.NET ID에 대한 Database-First 공급자를 만드는 방법


답변

좋은 질문.

저는 데이터베이스를 우선시하는 사람입니다. 코드 첫 번째 패러다임은 나에게 느슨해 보이며 “마이그레이션”은 오류가 발생하기 쉬운 것 같습니다.

aspnet ID 스키마를 사용자 지정하고 싶었고 마이그레이션에 신경 쓰지 않았습니다. 저는 Visual Studio 데이터베이스 프로젝트 (sqlpackage, data-dude)에 대해 잘 알고 있으며 스키마를 업그레이드하는 데 얼마나 좋은지 잘 알고 있습니다.

내 단순한 솔루션은 다음과 같습니다.

1) aspnet ID 스키마를 미러링하는 데이터베이스 프로젝트를 만듭니다. 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);
            }
        }
    }


답변

나는 이것을 통해 몇 시간을 보냈고 마침내 여기 내 블로그 에서 공유 한 해결책을 찾았 습니다 . 기본적으로 악취 의 대답 에서 말한 모든 작업을 수행해야 하지만 한 가지 추가 사항이 있습니다. Identity Framework에 응용 프로그램 엔터티에 사용되는 Entity Framework 연결 문자열 위에 특정 SQL-Client 연결 문자열이 있는지 확인하는 것입니다.

요약하면 애플리케이션은 Identity Framework에 연결 문자열을 사용하고 애플리케이션 엔터티에 다른 연결 문자열을 사용합니다. 각 연결 문자열은 다른 유형입니다. 전체 자습서를 보려면 내 블로그 게시물을 읽어보십시오.