【问题标题】:How can complex type property be used as identifier in Entity Framework AddOrUpdate method?Entity Framework AddOrUpdate 方法中如何使用复杂类型属性作为标识符?
【发布时间】:2017-04-04 07:10:40
【问题描述】:

在我的应用程序中,我有一个模型 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 =&gt; u.UserInfo.Username, user); 为用户表播种数据时, 我收到以下错误消息:

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 但我的目标是更“广泛”的解决方案。

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

【问题讨论】:

  • 只是好奇,如果您不执行 AddorUpdate,EF 是否会为您的复杂类型的属性创建列?
  • @Coding Yoshi EF 在我第一次以这种方式使用 AddOrUpdate 时添加列,但不为值设定种子,它会在后续种子中引发异常。当我使用不带标识符的 AddOrUpdate 时,它​​还会使用提供的值为表播种。

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


【解决方案1】:

如您所说,您将使其工作的唯一方法是将 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
}

希望这会有所帮助!

【讨论】:

  • 感谢您的建议。我知道复杂类型是必需的,但由于我在 UserInfo 中有必需的属性,所以无论如何我都会得到 ArgumentNullException。
【解决方案2】:

在不将Username 转移到User 的情况下,我能想到的唯一解决方案是首先检查Users 中是否存在具有给定UserInfo.Usernameuser 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
                                   }
                               };

然后将 AddOrUpdateparams TEntity[] entities 重载一起使用,它不会使用导致 InvalidOperationException 的“罪魁祸首”System.Linq.Expressions.Expression&lt;Func&lt;User, object&gt;&gt; expression

context.Users.AddOrUpdate(user);

EF 正确更新值,因此可以正常工作。 我仍然很难过,虽然您可以使用复杂类型进行查询,但您不能在 AddOrUpdate 扩展方法中使用复杂类型来更新数据库数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-17
    • 2011-10-05
    • 2016-05-23
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多