2014-11-06 2 views
2

Я решил использовать впервые Entity Framework 6.0. Так что да, я новичок в этом. Как всегда, я создал базу данных, а затем я производить код Первая модель (с помощью наглядного мастера студии), который выглядит следующим образом:Entity Framework 6.0 - Странное поведение при удалении

Partial Public Class DataContext 
Inherits DbContext 

Public Sub New() 
    MyBase.New("name=DataContext") 
End Sub 

Shared Sub New() 
    DbInterception.Add(New FullTextInterceptor()) 
End Sub 

Public Overridable Property StatusInfoes As DbSet(Of StatusInfo) 
Public Overridable Property UpdateSets As DbSet(Of UpdateSet) 
Public Overridable Property Users As DbSet(Of User) 

Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder) 
    modelBuilder.Configurations.Add(New UpdateSetFtsMap) 

    modelBuilder.Entity(Of StatusInfo)() _ 
     .Property(Function(e) e.Information) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of UpdateSet)() _ 
     .Property(Function(e) e.Title) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of UpdateSet)() _ 
     .Property(Function(e) e.Files) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of UpdateSet)() _ 
     .HasMany(Function(e) e.StatusInfoes) _ 
     .WithRequired(Function(e) e.UpdateSet) _ 
     .WillCascadeOnDelete(False) 

    modelBuilder.Entity(Of User)() _ 
     .Property(Function(e) e.Login) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of User)() _ 
     .Property(Function(e) e.Password) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of User)() _ 
     .Property(Function(e) e.Surname) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of User)() _ 
     .Property(Function(e) e.Name) _ 
     .IsUnicode(False) 

    modelBuilder.Entity(Of User)() _ 
     .HasMany(Function(e) e.StatusInfoes) _ 
     .WithRequired(Function(e) e.User) _ 
     .WillCascadeOnDelete(False) 
End Sub 

Public Function GetServerDate() As DateTime 
    Return Database.SqlQuery(Of DateTime)("Select GetDate()").SingleOrDefault 
End Function 

End Class 

Так у меня есть UpdateSet объект с, по меньшей мере, один StatusInfo объект. Пока все хорошо.

Странная вещь - удаление. Вот мой код:

Public Function DeleteById(id As Integer) As Integer Implements IDataMapper(Of UpdateSetDataTransferObject).DeleteById 
    Dim result = -1 

    Using ctx As New DataContext 
     Dim dbUpdateSet = (From o In ctx.UpdateSets Where o.Id = id Select o).SingleOrDefault 

     If dbUpdateSet IsNot Nothing Then 
      ctx.UpdateSets.Remove(dbUpdateSet) 

      Try 
       ctx.SaveChanges() 
       result = 0 
      Catch ex As DbUpdateException 
      End Try 
     End If 
    End Using 

    Return result 
End Function 

Странно, что иногда это работает. (1 из 20, скажем так). При отладке я заметил, что в большинстве случаев кода

ctx.UpdateSets.Remove(dbUpdateSet) 

удаляет все объекты StatusInfo (дочерние объекты) из коллекции StatusInfoes, так что я полагаю, что EF не имеет никакой информации о детях для удаления. Таким образом, я получаю сообщение об ошибке:

The DELETE statement conflicted with the REFERENCE constraint "FK_UpdateSetStatus_UpdateSet". The conflict occurred in database "UpdateWizard", table "dbo.StatusInfo", column 'UpdateSetId'. The statement has been terminated.

Как я уже упоминал ранее, есть несколько случаев, когда он работает. В те времена коллекция объектов StatusInfo не удалялась командой remove.

Может ли кто-нибудь помочь?

ответ

2

Причина, почему вы получаете эту ошибку

The DELETE statement conflicted with the REFERENCE constraint "FK_UpdateSetStatus_UpdateSet". The conflict occurred in database "UpdateWizard", table "dbo.StatusInfo", column 'UpdateSetId'.

на мой взгляд, не EF ошибка это ошибка приходит от сервера SQL, что касается того, что у вас есть ограничения внешнего ключа означает, что вы Канот удалить потому что другие записи зависят от него.

+1

@shadow Перед удалением UpdateSet вам необходимо удалить все записи StatusInfo с данным UpdateSetId. – dckuehn

+0

Спасибо вам за ваше время. Я знаю, что это от SQL Server, но я не понимаю, почему в некоторых случаях работает нормально, а в другом нет. @dckuehn Я думал, что это работа для EF. Я не хочу верить, что мы должны делать это для каждого отношения родитель-ребенок. Для меня проблема возникает в инструкции ctx.UpdateSets.Remove (dbUpdateSet). Как-то возникает мысль, что информация потеряна. – shadow

+0

Прошу прощения, я не могу быть более полезным. Компания, с которой я работаю, не верит в жесткое удаление каких-либо данных, мы устанавливаем 'Deleted = True' booleans везде, где нам нужно, поэтому я не знаком с удалением данных, хотя я много использую EF. Найдите «Cascading Delete», это может приблизиться к тому, что вам нужно. – dckuehn

1

Я нашел решение, и теперь это кажется очевидным. Мне просто нужно включить каскадное удаление по ограничению внешнего ключа между родительским (объект UpdateSet) и дочерними объектами (объект StatusInfo). Читая статью об изменении объектов в EF4.0, я попал в абзац, в котором говорится: «Включить или отключить каскадное удаление как в конфигурации базы данных, так и в конфигурации EF». В моем случае, поскольку сначала была создана база данных, это было отключено, поэтому, когда я создал модель (сначала код), она также была отключена в EF. Поэтому я предполагаю, что в этом случае мне пришлось удалить всех детей вручную. Честно говоря, потому что я старая школа, я не очень взволнован этим (каскадное удаление при ограничении), но я не могу представить другого способа для EF сделать это. Так что спасибо вам еще раз. Надеюсь, это поможет другим.

Смежные вопросы