У меня есть первое приложение базы данных MVC 5 / EF 6, использующее Identity 2. Модель Identity по умолчанию уже была изменена, чтобы включить UserRoles и несколько пользовательских свойств, сопоставленных со столбцами, которые я добавил в AspNetUsers - все до этого момента работало замечательно.
У меня есть новое требование добавить отношение «многие ко многим» к AspNetUsers под названием AspNetUserAgreements.Я добавил таблицу и внешние ключи в БД.
CREATE TABLE [dbo].[Agreement](
[AgreementID] [int] IDENTITY(1,1) NOT NULL,
[HTML] [varchar](max) NULL,
[Brief] [varchar](500) NULL,
[CreateDate] [datetime] NOT NULL CONSTRAINT [DF_Agreement_CreateDate] DEFAULT (getdate()),
[ChangeDate] [datetime] NULL,
[Active] [bit] NOT NULL CONSTRAINT [DF_Agreement_Active] DEFAULT ((1)),
[UserId] [nvarchar](128) NULL,
[Name] [varchar](50) NULL,
CONSTRAINT [PK_Agreement] PRIMARY KEY CLUSTERED
(
[AgreementID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Agreement] WITH CHECK ADD CONSTRAINT [FK_Agreement_AspNetUsers] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
GO
ALTER TABLE [dbo].[Agreement] CHECK CONSTRAINT [FK_Agreement_AspNetUsers]
GO
CREATE TABLE [dbo].[AspNetUserAgreement](
[UserId] [nvarchar](128) NOT NULL,
[AgreementID] [int] NOT NULL,
CONSTRAINT [PK_AspNetUserAgreement] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[AgreementID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetUserAgreement] WITH CHECK ADD CONSTRAINT [FK_AspNetUserAgreement_Agreement] FOREIGN KEY([AgreementID])
REFERENCES [dbo].[Agreement] ([AgreementID])
GO
ALTER TABLE [dbo].[AspNetUserAgreement] CHECK CONSTRAINT [FK_AspNetUserAgreement_Agreement]
GO
ALTER TABLE [dbo].[AspNetUserAgreement] WITH CHECK ADD CONSTRAINT [FK_AspNetUserAgreement_AspNetUsers] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
GO
ALTER TABLE [dbo].[AspNetUserAgreement] CHECK CONSTRAINT [FK_AspNetUserAgreement_AspNetUsers]
GO
У меня есть запись Соглашения, запись AspNetUser и запись aspnetUserAgreement, которая их связывает.Эти 3 таблицы импортированы в модель EF, и я могу видеть список соглашений от объекта AspNetUer, а также видеть список AspNetUsers от объекта соглашения.
ApplicationDbContext OnModelCreating имеет следующее:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AspNetUser>()
.ToTable("AspNetUser")
.HasKey(d => d.Id)
.HasMany(d => d.UserAgreements)
.WithMany(d => d.AspNetUsers)
.Map(m =>
{
m.MapLeftKey("Id");
m.MapRightKey("AgreementID");
});
modelBuilder.Entity<ApplicationUser>()
.HasMany(d => d.UserAgreements)
.WithMany(d => d.ApplicationUsers)
.Map(m =>
{
m.MapLeftKey("Id");
m.MapRightKey("AgreementID")
});
modelBuilder.Entity<ApplicationUserRole>()//.ToTable("ApplicationUserRole")
.HasKey(ur => new { ur.UserId, ur.RoleId });
modelBuilder.Entity<ApplicationUserRole>()
.HasRequired(r => r.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId);
modelBuilder.Entity<ApplicationUserRole>()//.ToTable("ApplicationRole")
.HasRequired(ur => ur.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId);
base.OnModelCreating(modelBuilder);
}
ApplicationUser имеет следующее:
public class ApplicationUser : IdentityUser<string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>
{
public ApplicationUser()
{
UserAgreements = new HashSet<Agreement>();
UserRoles = new List<ApplicationUserRole>();
Id = Guid.NewGuid().ToString();
}
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, string> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
if (MemberDirectoryID.HasValue)
{
userIdentity.AddClaim(new Claim("Toolbar", this.Toolbar));
userIdentity.AddClaim(new Claim("HasSignedAgreement", this.HasSignedAgreement.ToString()));
//userIdentity.AddClaim(new Claim("NewMemberTemporaryGUID", this.NewMemberTemporaryGUID));
return userIdentity;
}
public string Toolbar
{
get
{
return ((List<ApplicationUserRole>)UserRoles).Any(a => a.Role.Name == "Admin") ? "admin" : "member";
}
}
public bool HasSignedAgreement
{
get
{
return ((HashSet<Agreement>)UserAgreements).Any();
}
}
public ICollection<ApplicationUserRole> UserRoles { get; set; }
public ICollection<Agreement> UserAgreements { get; set; }
}
Объект соглашения создан EF, но у меня есть этот частичный класс для его расширения:
public interface IAgreement
{
}
[MetadataType(typeof(IAgreement))]
public partial class Agreement : IAgreement
{
public virtual ICollection<ApplicationUser> ApplicationUsers { get; set; } = new HashSet<ApplicationUser>();
}
Мне нужен код идентификации, чтобы вернуть моему ApplicationUser со списком пользовательских соглашений, заполненных соглашениями.Это должно быть сделано изначально при входе в систему, потому что есть специальный атрибут фильтра, который проверяет количество UserAgreements, а затем направляет пользователя в зависимости от значения.
Оператор задачи: При вызове Identityобъекты кажутся правильно структурированными, т.е. у моего ApplicationUser есть коллекция соглашений, называемых UserAgreements, но она пуста.Нет ошибок, нет данных.Соглашения никогда не загружаются ... Я, должно быть, что-то упускаю, так как, если я вызываю модельный контекст, я могу получить Соглашения от AspNetUser и я могу получить ApplicationUsers из Соглашения.
Любая помощь приветствуется, спасибо!