我有以下一段代码
var newPost = new Post()
{
Activity = new Activity { Type = 1, ActivityTotalStatistic = new ActivityTotalStatistic() },
CreatedDate = oldPost.DateTimeCreated,
CategoryId = categoryId,
Title = oldPost.Name,
OwnerId = oldPost.UserID,
Slug = oldPost.Name,
LastUpdateDate = oldPost.DateTimeCreated,
PublishDate = oldPost.DateTimeCreated,
PostStatistic = new PostStatistic(),
PostItems = new List<PostItem>
{
new PostItem
{
Activity = new Activity { Type = 2},<-- note this line of code
CreatedDate = oldPost.DateTimeCreated,
Title = oldPost.Name,
Type = 1,
Content = oldPost.Path
}
}
};
newDb.Posts.Add(newPost);
newDb.SaveChanges();
这是活动和统计信息表的SQL模式
create table ActivityTotalStatistics
(
Id int primary key identity(1,1),
NumberOfLikes int not null,
NumberOfDislikes int not null,
SumOfLikes int not null,
CommentCount int not null
)
create table Activities
(
Id int identity (1,1) primary key,
Type int not null,
ActivityTotalStatisticId int not null
foreign key references ActivityTotalStatistics(Id)
)
如您所见,每个活动都应该具有活动统计信息,因为外键不可为空,并且我的代码应该中断,因为发布项目中的活动没有实例化活动统计信息。
但是EF无法识别它。发生的情况是,该项目从该行代码接收到相同的活动统计信息
Activity = new Activity { Type = 1, ActivityTotalStatistic = new ActivityTotalStatistic() },
这是实体框架的有效行为吗?
更新 Activity.cs模型
public partial class Activity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Activity()
{
this.ActivityLikes = new HashSet<ActivityLike>();
this.Comments = new HashSet<Comment>();
this.PostItems = new HashSet<PostItem>();
this.Posts = new HashSet<Post>();
}
public int Id { get; set; }
public int Type { get; set; }
public int ActivityTotalStatisticId { get; set; }
public virtual ActivityTotalStatistic ActivityTotalStatistic { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ActivityLike> ActivityLikes { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PostItem> PostItems { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Post> Posts { get; set; }
}
ActivityTotalStatistic.cs
public partial class ActivityTotalStatistic
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public ActivityTotalStatistic()
{
this.Activities = new HashSet<Activity>();
}
public int Id { get; set; }
public int NumberOfLikes { get; set; }
public int NumberOfDislikes { get; set; }
public int SumOfLikes { get; set; }
public int CommentCount { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Activity> Activities { get; set; }
}
答案 0 :(得分:4)
这是实体框架的有效行为吗?
我不这么认为-不幸的是,对于这些跟踪行为,没有正式的文档/规范,但看起来像实现特定的副作用/缺陷(错误)。
理论价格:
仅当更改跟踪器包含具有自动生成的PK的单个 Added
主实体,从属实体同时具有显式引用导航属性和FK属性时,才会发生全部具有默认值(“ 0”和null
)。
在以下情况下不会发生 :
(1)有第二个Added
主要实体:
newDb.Set<ActivityTotalStatistic>().Add(new ActivityTotalStatistic());
SaveChanges
抛出DbUpdateException
:
无法确定“ Activity_ActivityTotalStatistic”关系的主要终点。添加的多个实体可能具有相同的主键。
不太用户友好,但仍然是例外。
(2)从属实体没有显式的FK属性,但是正确配置了必需的影子FK属性。 SaveChanges
引发:
“ MyDbContext.Activities”中的实体参与“ Activity_ActivityTotalStatistic”关系。找到0个相关的'Activity_ActivityTotalStatistic_Target'。 1个预期为“ Activity_ActivityTotalStatistic_Target”。
虽然不是很友好,但还是有例外。
(3)引用导航属性已应用[Required]
属性:
[Required]
public virtual ActivityTotalStatistic ActivityTotalStatistic { get; set; }
SaveChanges
抛出包含ValidationException
的{{1}},并带有(最终)用户友好消息:
ActivityTotalStatistic字段为必填字段。
回到原始情况。仅且仅在该特定情况下,EF会找到单个挂起的ValidationError
主实体实例,并将其与具有Added
和ActivityTotalStatistic == null
的所有挂起的从属实体相关联。
对我来说,所有这些都表明错误/意外的EF6行为。防止它的最好方法似乎是用ActivityTotalStatisticId == 0
]属性修饰必需的参考导航属性,但是在像您这样的数据库优先(edmx)生成的实体模型中存在问题。