gpt4 book ai didi

c# - 具有简单一对多的 Entity Framework "The relationship could not be changed"

转载 作者:太空宇宙 更新时间:2023-11-03 13:36:52 24 4
gpt4 key购买 nike

我正在尝试删除与以下代码的关系:

                var serverVideo = InternalGetVideo(db, videoId);

// get owning user
var owner = InternalGetUser(db, serverVideo.UserId);

// Add/remove video to user's upvotedVideos
if (owner.UpvotedVideos.Contains(serverVideo))
{
serverVideo.UpVotes--;
SaveChanges(db); // Works
owner.UpVotes--;
SaveChanges(db); // Works
owner.UpvotedVideos.Remove(serverVideo);
SaveChanges(db); // Breaks
}

SaveChanges(db);

但我总是得到这个错误:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

我不是要删除视频,我只是想将它从用户的 UpvotedVideos 属性中删除(它就在那里):

[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Username { get; set; }
public int UpVotes { get; set; }
public virtual List<Video> UpvotedVideos { get; set; }
public string Email { get; set; }
}

Videos 不包含对 UserProfiles 的引用 - 它是一对多关系。知道我做错了什么吗?

视频类:

[DataContract]
public class Video
{
[Key]
[DataMember(IsRequired = false)]
public int VideoId { get; set; }

[DataMember(IsRequired = false)]
public int UserId { get; set; } // user that created the video, unrelated

[Required]
[DataMember]
public virtual IList<Tag> Tags { get; set; }

}

最佳答案

您在源代码中的注释:

public int UserId { get; set; }  // user that created the video, unrelated

不相关?这很可能是所讨论的一对多关系的外键,因为映射约定会将其检测为外键,因为它与主键属性同名UserProfile 中的 UserId。并且由于该属性具有不可为 null 的类型 int EF 会将这种关系检测为必需,这意味着没有用户点赞的视频就不可能存在。

这是当您从 UpvotedVideos 集合中删除视频时出现的异常,这意味着与当前点赞该视频的用户的关系已删除。您可以这样做,但是因为每个视频都必须有一个用户点赞它,所以您必须将该视频分配给另一个用户或完全删除该视频。

好吧,显然您不希望视频必须有用户对其点赞,而是视频可以没有任何点赞。在这种情况下,关系必须是可选的。您可以通过多种方式实现这一目标:

  • 通过重命名 UserId 属性打破常规映射,例如

    public int CreatorId { get; set; }  // user that created the video, unrelated

    现在,这个属性真的不相关,只是一个完全没有关系的标量属性。默认情况下,UpvotedVideos 集合引入的关系现在是可选的,因为它在另一端没有必需的外键属性。

  • 使用 Fluent API 覆盖映射约定:

    modelBuilder.Entity<UserProfile>()
    .HasMany(u => u.UpvotedVidoes)
    .WithOptional()
    .Map(m => m.MapKey("UpvoterId")); // <- FK column name
  • 引入第二个(可为空的)属性并将其定义为带有数据注释的外键:

    [DataContract]
    public class Video
    {
    [Key]
    [DataMember(IsRequired = false)]
    public int VideoId { get; set; }

    [DataMember(IsRequired = false)]
    public int UserId { get; set; } // user that created the video, unrelated

    public int? UpvoterId { get; set; }

    [Required]
    [DataMember]
    public virtual IList<Tag> Tags { get; set; }
    }

    UserProfile 中:

    [ForeignKey("UpvoterId")]
    public virtual List<Video> UpvotedVideos { get; set; }

可能有更多的变体,包括在 Video 中添加导航属性等。但在所有情况下,必须将关系定义为可选关系才能使您的代码正常工作。

旁注:这种关系不应该是多对多的吗?一个用户可以给很多视频点赞,一个视频可以被很多用户点赞吗?但这是另一个问题...

关于c# - 具有简单一对多的 Entity Framework "The relationship could not be changed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18410327/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com