Entity Framework 6, проверка не работает, как задумано - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть следующий фрагмент кода

 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() },

Это допустимое поведение Entity Framework?

UPDATE Модель 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; }
    }

1 Ответ

0 голосов
/ 20 февраля 2019

Является ли это допустимым поведением Entity Framework?

Я так не думаю - к сожалению, нет официальной документации / спецификации для этих способов отслеживания, но выглядит как сторона, зависящая от реализацииэффект / дефект (ошибка).

Обоснование:

Это происходит только , когда трекер изменений содержит один Added основной объект с автоматически сгенерированным PK,у зависимого объекта есть как явное ссылочное свойство навигации, так и свойство FK, все со значениями по умолчанию ('0' и null).

Это не происходит, если:

(1) Существует второй Added основной объект:

newDb.Set<ActivityTotalStatistic>().Add(new ActivityTotalStatistic());

SaveChanges throws DbUpdateException:

Невозможно определить основной конец 'Activity_ActivityTotalStatistic'отношения.Несколько добавленных объектов могут иметь один и тот же первичный ключ.

Не очень удобно для пользователя, но все еще исключение.

(2) У зависимого объекта нет явного свойства FK, но требуется правильно настроенныйтеневая собственность ФК.SaveChanges throws:

Объекты в «MyDbContext.Activities» участвуют в отношении «Activity_ActivityTotalStatistic».0 связанных 'Activity_ActivityTotalStatistic_Target' были найдены.1 'Activity_ActivityTotalStatistic_Target' ожидается.

Опять не очень удобно, но все же исключение.

(3) Свойство ссылочной навигации имеет атрибут [Required]:

[Required]
public virtual ActivityTotalStatistic ActivityTotalStatistic { get; set; }

SaveChanges бросков ValidationException, содержащих ValidationError с (наконец) удобным для пользователя сообщением:

Поле ActivityTotalStatistic является обязательным.


Вернуться к исходному случаю.Только и только в этом конкретном случае EF находит единственный ожидающий экземпляр Added основного объекта и связывает его со всеми ожидающими зависимыми объектами, имеющими ActivityTotalStatistic == null и ActivityTotalStatisticId == 0.

Все это для меня указывает на ошибку / непреднамеренноеEF6 поведение.Наилучшим способом предотвращения этого является декорация требуемых справочных навигационных свойств с атрибутом [Required], но это проблематично в модели сущностей, сгенерированной Database First (edmx), как у вас.

...