ProjectName.Core
ライブラリには、すべてのビジネスロジックとエンティティ、およびそれらの動作が含まれています。 Entity Frameworkや他のDALとは何の関係もありません。それらを分離しておくのが好きだからです。 Entity Frameworkの構成(Fluent APIを使用)はProjectName.Infrastructure
プロジェクト。これにより、エンティティをEFにプッシュすることができます。基本的には、オニオンのようなアーキテクチャの方向に進んでいます。
ただし、ASP.NET Identityフレームワークをミックスに追加する場合、ApplicationUser
エンティティをIdentityUser
クラスから継承する必要がありますが、ApplicationUser
クラスは他のエンティティと関係があります。 IdentityUser
からの継承では、エンティティプロジェクトにEntity Frameworkへの参照を導入しています。これは、そうしたくない場所の1つです。 Entity FrameworkベースのIDシステムを使用しているため、ApplicationUser
クラスをエンティティプロジェクトからInfrastructure
プロジェクトにプルすると、循環参照が発生するため、これを行う方法ではありませんどちらかに行きます。
これを回避する方法はありますか?ASP.NET Identityを使用しない以外に、2つのレイヤー間のクリーンな分離を維持できますか?
コアライブラリにASP.NET Identityとは関係のないserクラスを作成できます。
public class User {
public Guid UserId { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
public string EmailAddressConfirmed { get; set; }
public string PhoneNumber { get; set; }
public string PhoneNumberConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
...
public virtual ICollection<Role> Roles { get; set; }
public virtual ICollection<UserClaim> UserClaims { get; set; }
public virtual ICollection<UserLogin> UserLogins { get; set; }
}
Entity Frameworkを使用している場合は、エンティティの構成クラスを作成します(オプション)。
internal class UserConfiguration : EntityTypeConfiguration<User>
{
internal UserConfiguration()
{
ToTable("User");
HasKey(x => x.UserId)
.Property(x => x.UserId)
.HasColumnName("UserId")
.HasColumnType("uniqueidentifier")
.IsRequired();
Property(x => x.PasswordHash)
.HasColumnName("PasswordHash")
.HasColumnType("nvarchar")
.IsMaxLength()
.IsOptional();
Property(x => x.SecurityStamp)
.HasColumnName("SecurityStamp")
.HasColumnType("nvarchar")
.IsMaxLength()
.IsOptional();
Property(x => x.UserName)
.HasColumnName("UserName")
.HasColumnType("nvarchar")
.HasMaxLength(256)
.IsRequired();
// EmailAddress, PhoneNumber, ...
HasMany(x => x.Roles)
.WithMany(x => x.Users)
.Map(x =>
{
x.ToTable("UserRole");
x.MapLeftKey("UserId");
x.MapRightKey("RoleId");
});
HasMany(x => x.UserClaims)
.WithRequired(x => x.User)
.HasForeignKey(x => x.UserId);
HasMany(x => x.UserLogins)
.WithRequired(x => x.User)
.HasForeignKey(x => x.UserId);
}
}
Role、UserClaim、およびUserLoginのクラスも作成する必要があります。上記の名前が気に入らない場合は、好きな名前を付けることができます。
Webレイヤーで、AppUser(または、選択した場合は別の名前)というクラスを作成します。このクラスはASP.NET Identity IUser <TKey>インターフェイスを実装する必要があります。ここで、-TKeyは主キーのデータ型です(Guid上記の例)。
public class AppUser : IUser<Guid>
{
public AppUser()
{
this.Id = Guid.NewGuid();
}
public AppUser(string userName)
: this()
{
this.UserName = userName;
}
public Guid Id { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
public string EmailAddressConfirmed { get; set; }
public string PhoneNumber { get; set; }
public string PhoneNumberConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
}
Webプロジェクト内のUserManagerへのすべての参照をserManager <AppUser、Guid>に変更します。
最後に、独自のserStoreを作成します。基本的に、カスタムUserStoreはAppUserオブジェクトを受け取り、それをserエンティティオブジェクトに変換して永続化します。これらのメソッドの1つの例を以下に示します。
public class UserStore :
IUserLoginStore<AppUser, Guid>,
IUserClaimStore<AppUser, Guid>,
IUserRoleStore<AppUser, Guid>,
IUserPasswordStore<AppUser, Guid>,
IUserSecurityStampStore<AppUser, Guid>,
IUserStore<AppUser, Guid>,
IDisposable
{
private User MapFromAppUser(AppUser appUser)
{
if (appUser == null)
return null;
var userEntity = new User();
PopulateUser(userEntity, appUser);
return userEntity;
}
private void PopulateUser(User user, AppUser appUser)
{
user.UserId = appUser.Id;
user.UserName = appUser.UserName;
user.EmailAddress = appUser.EmailAddress;
user.EmailAddressConfirmed = appUser.EmailAddressConfirmed;
user.PhoneNumber = appUser.PhoneNumber;
user.PhoneNumberConfirmed = appUser.PhoneNumberConfirmed;
user.PasswordHash = appUser.PasswordHash;
user.SecurityStamp = appUser.SecurityStamp;
// First name, last name, ...
}
#region IUserStore<AppUser, Guid> Members
public Task CreateAsync(AppUser appUser)
{
if (appUser == null)
throw new ArgumentNullException("appUser");
var userEntity = MapFromAppUser(appUser);
// Persist the user entity to database using a data repository.
// I'll leave this to you.
}
...
#endregion
}
可能な実装の完全な説明を取得するには、 ここ をクリックします。
結局、それはあなたの選択です。コアライブラリのIdentityフレームワークを参照するだけでなく、この実装を維持するために必要な労力を測定します。個人的には、上記で説明した方法で行うことを考えましたが、ASP.NET Identityフレームワークが更新されるたびにコードを変更する必要がある可能性があるため、そうしませんでした。
うまくいけば、これがあなたの質問に役立ち、答えます!