由于检测到要保存的数据存在循环依赖关系,因此无法保存更改。

3
我将尝试在我的上下文中添加一个 ApplicationUserPerson 实体。
我的 ApplicationUser 类。
public class ApplicationUser : IdentityUser<Guid>
{
    public int? PersonID { get; set; }

    [ForeignKey("PersonID")]
    public Person Person { get; set; }

    [InverseProperty("User")]
    public ICollection<UserSource> UserSources { get; set; }

    public virtual ICollection<IdentityUserClaim<Guid>> Claims { get; set; }
    public virtual ICollection<IdentityUserLogin<Guid>> Logins { get; set; }
    public virtual ICollection<IdentityUserToken<Guid>> Tokens { get; set; }
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

我的 Person
public class Person : BaseEntity
{
    [Required]
    [DataType(DataType.Text)]
    public string FirstName { get; set; }

    [Required]
    [DataType(DataType.Text)]
    public string LastName { get; set; }

    [Required]
    [DataType(DataType.Text)]
    public string FullName { get; set; }

    public int HeightInches { get; set; }

    public int WeightPounds { get; set; }

    [DataType(DataType.Text)]
    public string BatHand { get; set; }

    [DataType(DataType.Text)]
    public string ThrowHand { get; set; }

    public DimDate BirthDate { get; set; }

    public DimDate DeathDate { get; set; }

    public DimDate DebutDate { get; set; }
    public DimDate FinalDate { get; set; }
    public Guid? UserID { get; set; }

    [ForeignKey("UserID")]
    public ApplicationUser User { get; set; }

    [InverseProperty("LeagueOwner")]
    public ICollection<League> LeaguesOwned { get; set; }

    public override int GetHashCode() => Tuple.Create(this.FirstName, this.LastName, this.FullName).GetHashCode();
}

我正在尝试创建这两个实体,然后在我的UserServiceRegisterUser方法中将它们绑定在一起。

Public Class UserService : IUserService
{
    private MyDbContext context;
    private ILogger logger;
    private UserManager<ApplicationUser> userManager;

    public async Task<ApplicationUser> RegisterUser(RegistrationModel registrationModel)
    {
        // Create the User first
        var user = new ApplicationUser
        {
            UserName = registrationModel.UserName,
            Email = registrationModel.Email
        };

        // Create the User with a password
        var result = await this.userManager.CreateAsync(user, registrationModel.Password);

        // Make sure the user is successfully created
        if (result.Succeeded)
        {
            try
            {
                this.logger.LogInformation($"User {user.UserName} successfully created and added to the database");

                // create a person for the User (this is causing me to have a headache...)
                // I originally had this is separate methods... moving into one so I can make more sense
                var fullName = (registrationModel.FirstName == registrationModel.LastName) ? registrationModel.FirstName : registrationModel.FirstName + " " + registrationModel.LastName;
                var newPerson = new Person
                {
                    FirstName = registrationModel.FirstName,
                    LastName = registrationModel.LastName,
                    FullName = fullName
                };

                // Add the person to the DB
                await this.context.People.AddAsync(newPerson);

                // Add the User to the Person and vice versa
                user.Person = newPerson;
                newPerson.User = user;

                // Save the changes
                await this.context.SaveChangesAsync();
                this.logger.LogInformation($"Person for {user.NormalizedUserName} created");

                // Add source to the user
                var userSource = new UserSource
                {
                    MySource = registrationModel.WhereDidYouHear,
                    User = user
                };

                await this.context.UserSources.AddAsync(userSource);
                this.logger.LogInformation($"Source added to UserSources for {user.NormalizedUserName}");

                return user;
            }
            catch (Exception e)
            {
                this.logger.LogError(e);
                return null;
            }
        }
        foreach (var error in result.Errors)
        {
            this.logger.LogError(error.Description);
        }

        return null;
    }
}

然而,当该方法执行时,我的日志中出现了以下错误:
System.InvalidOperationException: 无法保存更改,因为在要保存的数据中检测到循环依赖关系: 'Person [Added] <- Person { 'PersonID' } ApplicationUser [Added] <- User { 'UserID' } Person [Added]'
据我所知,我认为我已经正确设置了ApplicationUser和Person之间的关系,所以我不确定为什么它不允许我将Person附加到ApplicationUser,反之亦然。
为了参考,我将包括RegistrationModel,因为其中的数据被用于RegisterUser方法。
public class RegistrationModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [RegularExpression(@"^[a-zA-Z0-9_]{5,255}$")]
    [Required]
    [StringLength(256)]
    [Display(Name = "UserName")]
    public string UserName { get; set; }

    [Required]
    [StringLength(256)]
    public string FirstName { get; set; }

    [Required]
    [StringLength(256)]
    public string LastName { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    [DataType(DataType.Text)]
    [Display(Name = "Where did you hear about us?")]
    public string WhereDidYouHear { get; set; }
}

2
如果你的Person有一个外键指向你的ApplicationUser,而你的ApplicationUser又有一个外键指向你的Person,那么当它们都依赖于对方的创建来获得ID作为外键时,如何创建其中之一呢?当外键实体尚未被创建时? - undefined
...那是一个非常好的问题。所以我只需要指向其中一个而不是相反吗? - undefined
这个回答解决了你的问题吗?Entity Framework Code First 一对一关系 - undefined
1个回答

1
我能够通过删除我的AspNetUser类中的PersonID属性,并基于 这篇教程来进行新的设置,来解决这个问题。
这是我调整后的AspNetUser类:
public class ApplicationUser : IdentityUser<Guid>
{
    [InverseProperty("User")]
    public Person Person { get; set; }

    [InverseProperty("User")]
    public ICollection<UserSource> UserSources { get; set; }

    [InverseProperty("Owner")]
    public ICollection<League> LeaguesOwned { get; set; }

    public virtual ICollection<IdentityUserClaim<Guid>> Claims { get; set; }
    public virtual ICollection<IdentityUserLogin<Guid>> Logins { get; set; }
    public virtual ICollection<IdentityUserToken<Guid>> Tokens { get; set; }
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

我的Person类没有变化,因此我调整了UserService中的RegisterUser方法如下:

public class UserService : IUserService
{
    private StatPeekContext context;
    private ILogger logger;
    private UserManager<ApplicationUser> userManager;

    /// <summary>
    /// This will register a new user
    /// </summary>
    /// <param name="registrationModel"></param>
    /// <returns></returns>
    public async Task<ApplicationUser> RegisterUser(RegistrationModel registrationModel)
    {
        // Create the User first
        var user = new ApplicationUser
        {
            UserName = registrationModel.UserName,
            Email = registrationModel.Email
        };

        // Create the User with a password
        var result = await this.userManager.CreateAsync(user, registrationModel.Password);

        // Make sure the user is successfully created
        if (result.Succeeded)
        {
            try
            {
                this.logger.LogInformation($"User {user.UserName} successfully created and added to the database");

                var fullName = (registrationModel.FirstName == registrationModel.LastName) ? registrationModel.FirstName : registrationModel.FirstName + " " + registrationModel.LastName;
                var newPerson = new Person
                {
                    FirstName = registrationModel.FirstName,
                    LastName = registrationModel.LastName,
                    FullName = fullName,
                    UserID = user.Id
                };

                // Add the person to the DB
                await this.context.People.AddAsync(newPerson);

                this.logger.LogInformation($"Person for {user.NormalizedUserName} created");

                // Add source to the user
                var userSource = new UserSource
                {
                    MySource = registrationModel.WhereDidYouHear,
                    UserID = user.Id
                };

                await this.context.UserSources.AddAsync(userSource);
                await this.context.SaveChangesAsync();
                this.logger.LogInformation($"Source added to UserSources for {user.NormalizedUserName}");

                return user;
            }
            catch (Exception e)
            {
                this.logger.LogError(e);
                return null;
            }
        }
        foreach (var error in result.Errors)
        {
            this.logger.LogError(error.Description);
        }

        return null;
    }
}

这看起来解决了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接