如何在Entity Framework AddOrUpdate方法中将复杂类型属性用作标识符?

时间:2016-11-20 23:55:38

标签: c# entity-framework ef-code-first entity-framework-6 ef-migrations

在我的应用程序中,我有一个模型User

public class User
{
    private ICollection<User> friends;
    private ICollection<Album> albums;

    public User()
    {
        this.albums = new HashSet<Album>();
        this.friends = new HashSet<User>();
    }

    public int Id { get; set; }

    public UserInfo UserInfo { get; set; }

    public int BornTownId { get; set; }

    public Town BornTown { get; set; }


    public int CurrentLivingTownId { get; set; }

    public Town CurrentLivingTown { get; set; }

    public virtual ICollection<User> Friends
    {
        get
        {
            return this.friends;
        }
        set
        {
            this.friends = value;
        }
    }

    public virtual ICollection<Album> Albums
    {
        get
        {
            return this.albums;
        }
        set
        {
            this.albums = value;
        }
    }
}

此处,UserInfo是一个复杂类型,如下所示:

[ComplexType]
public class UserInfo
{
    [Required]
    [MaxLength(30)]
    [MinLength(2)]
    [Column("FirstName",TypeName = "varchar")]
    public string FirstName { get; set; }

    [Required]
    [MaxLength(30)]
    [MinLength(2)]
    [Column("LastName", TypeName = "varchar")]
    public string LastName { get; set; }

    [NotMapped]
    public string FullName => this.FirstName + " " + this.LastName;

    [Required]
    [MaxLength(30)]
    [MinLength(4)]
    [Column("Username", TypeName = "varchar")]
    public string Username { get; set; }

    [Required]
    [MinLength(6)]
    [MaxLength(50)]
    [Column("Password", TypeName = "varchar")]
    [PasswordValidation]
    public string Password { get; set; }

    [Required]
    [Column("Email", TypeName = "varchar")]
    [DataType(DataType.EmailAddress)]
    [EmailValidation]
    public string Email { get; set; }

    [Column("RegisteredOn")]
    public DateTime RegisteredOn { get; set; }

    [Column("LastTimeLoggedIn")]
    public DateTime LastTimeLoggedIn { get; set; }

    [Range(1, 120)]
    [Column("Age")]
    public int Age { get; set; }

    [Column("IsDeleted")]
    public bool IsDeleted { get; set; }
}

当我尝试使用context.Users.AddOrUpdate(u => u.UserInfo.Username, user);为Users表播种数据时, 我收到以下错误消息:

Message=The properties expression 'u => u.UserInfo.Username' is not valid. The expression should represent a property: C#: 't => t.MyProperty'.

我的问题(与问题的目标一样复杂)是: 在AddOrUpdate中使用u.UserInfo.Username作为标识符的正确语法方法是什么,我应该向UserInfo类或属性添加任何标记,还是使用FluentApi进行更改,这是我正在尝试做的事情使用AddOrUpdate的正确方法。

我意识到我可以将Username从UserInfo中取出并直接放在User中,但我的目标是更多&#34;广泛的&#34;溶液

任何帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:0)

如你所说,你可以将UserName属性移到User类的唯一方法就是使用它。

AddOrUpdate要求您传递目标类型的简单属性以便正确执行,或者要传递匿名对象,以防您想要使用多个属性匹配您的实体,但它会抱怨你传递任何其他类型的表达函数。

因此,我建议您在User类上声明Username属性。

其他建议:请记住始终初始化复杂类型:

public class User
{
    private ICollection<User> friends;
    private ICollection<Album> albums;

    public User()
    {
        this.albums = new HashSet<Album>();
        this.friends = new HashSet<User>();

        //Good practice: always initialize your complex type properties
        UserInfo = new UserInfo();
    }

    //the rest of your class members here
}

希望这有帮助!

答案 1 :(得分:0)

如果不将;转移到Username,我能想到的唯一解决方案是首先检查User {中是否存在user给定UserInfo.Username Users {1}}:

DbSet

然后将var user = context.Users.FirstOrDefault(u => u.UserInfo.Username == username) ?? new User { UserInfo = new UserInfo() { FirstName = firstName, LastName = lastName, Username = username, Password = password, Email = email, RegisteredOn = registeredOnDate.AddDays(2), LastTimeLoggedIn = lastDateLoggedOn.AddDays(10), IsDeleted = isDeleted } }; AddOrUpdate重载一起使用,该重载不会导致导致InvalidOperationException的“罪魁祸首”params TEntity[] entities

System.Linq.Expressions.Expression<Func<User, object>> expression

context.Users.AddOrUpdate(user); 正确更新值,因此可行。 我仍然很遗憾,虽然您可以使用复杂类型进行查询,但您无法在EF扩展方法中使用复杂类型来更新数据库数据。