Репозиторий EF DBContext

мой вопрос состоит из двух частей.

Я использую репозиторий и шаблон единицы работы с сущностью. У меня есть следующие StockTransferRepository, и StockTransfer — это мой агрегатный корень.

Public Class StockTransferRepository
    Inherits WMSBaseRepository(Of StockTransfer, Int64, Dictionary(Of String, String))
    Implements IStockTransferRepository

    Public Sub New(uow As IUnitOfWork)
        MyBase.New(uow)
    End Sub

    Public Overrides Function GetObjectSet() As IQueryable(Of StockTransfer)
        Return DataContextFactory.GetWMSDBContext().StockTransfer
    End Function

    Public Overloads Sub Add(entity As StockTransfer) Implements IStockTransferRepository.Add
        MyBase.Add(entity)
    End Sub

    ' removes a stock transfer item
    Public Sub RemoveStockTransferItem(stockTransferItem As StockTransferItem) Implements IStockTransferRepository.RemoveStockTransferItem
        GetObjectContext().DeleteObject(stockTransferItem)
    End Sub

    Public Overloads Sub Remove(entity As StockTransfer) Implements IStockTransferRepository.Remove
        MyBase.Remove(entity)
    End Sub

    Public Overloads Sub Save(entity As StockTransfer) Implements IStockTransferRepository.Save
        MyBase.Save(entity)
    End Sub


    ' find the stock transfer by ID
    Public Overrides Function FindBy(id As Int64) As IQueryable(Of StockTransfer) Implements IStockTransferRepository.FindBy
        Return GetObjectSet.Where(Function(st) st.Id = id)
    End Function

End Class

Ниже приведен мой код для WMSBaseRepository.

Public MustInherit Class WMSBaseRepository(Of T As IAggregateRoot, TEntityKey, dbErr)
    Inherits Repository(Of T, TEntityKey)
    Implements IUnitOfWorkRepository

    Public Sub New(uow As IUnitOfWork)
        MyBase.New(uow)
    End Sub

    Public Function GetObjectContext() As ObjectContext
        Return DirectCast(DataContextFactory.GetWMSDBContext(), IObjectContextAdapter).ObjectContext
    End Function

    Public Sub PersistCreationOf(entity As IAggregateRoot) Implements IUnitOfWorkRepository.PersistCreationOf
        DataContextFactory.GetWMSDBContext.Entry(entity).State = EntityState.Added
    End Sub

    Public Sub PersistDeletionOf(entity As IAggregateRoot) Implements IUnitOfWorkRepository.PersistDeletionOf
        ' BEWARE!!!!!!!!!!!!!!!! Use with caution
        ' this will completely delete the record from the database
        DataContextFactory.GetWMSDBContext().Entry(entity).State = EntityState.Deleted
    End Sub

    Public Sub PersistUpdateOf(entity As IAggregateRoot) Implements IUnitOfWorkRepository.PersistUpdateOf
        DataContextFactory.GetWMSDBContext().Entry(entity).State = EntityState.Modified
    End Sub

End Class

Код ниже используется на моем сервисном уровне.

Public Function StockTransferItemRemove(removeRequest As StockTransferItemRequest) As StockTransferItemResponse Implements IStockTransferService.StockTransferItemRemove
        ' create your objects
        Dim removeResponse = New StockTransferItemResponse
        Dim stockTransfer As New StockTransfer

        Try

            ' get the aggregate root
            stockTransfer = _stockTransferRepository.FindBy(removeRequest.StockTransferID).FirstOrDefault

            For Each item In stockTransfer.StockTransferItems.ToList
                If (item.Id = removeRequest.StockTransferItemView.Id) Then
                    _stockTransferRepository.RemoveStockTransferItem(item)
                End If
            Next

            ' now save the stock transfer
            _stockTransferRepository.Save(stockTransfer)

            Dim count As Integer = _uow.WMSCommit()

            If (count > 0) Then
                ' the object was saved successfully
                removeResponse.Success = True
            Else
                ' the object was not saved successfully
                removeResponse.BrokenRules.Add(New BusinessRule(String.Empty, String.Empty, Tags.Messages.Commit_Failed))
            End If

        Catch ex As Exception
            ' an unexpected error occured
            removeResponse.BrokenRules.Add(New BusinessRule(String.Empty, String.Empty, ex.Message))
        End Try


        Return removeResponse
    End Function

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

Моя первая проблема заключается в том, что внутри WMSBaseRepository у меня есть функция с именем GetObjectContext, которая преобразует мой DBContext в ObjectContextAdapter.

Кто-нибудь знает, есть ли альтернатива для DBContext, иначе в чем смысл DBContext, если все примеры, которые я нахожу для удаления дочернего объекта, используют ObjectContext?

Моя вторая проблема, которую я пытаюсь понять с помощью DDD и уровня репозитория, заключается в том, что этот StockTransferRepository несет единоличную ответственность за совокупный корень StockTransfer, но мне нужно удалить StockTransferItem из StockTransfer. Правильно ли я делаю это, удаляя объект StockTransferItem, используя DeleteObject в StockTransferRepository?

Я надеюсь, что кто-то может указать мне в правильном направлении. Код работает правильно, но этот пост в основном посвящен тому, чтобы понять, правильный ли я делаю подход или нет.

Теперь я добавил следующее в свой сервисный слой вместо того, чтобы идти в репозиторий, чтобы удалить StockTransferItem.

            Dim product As New ProductInfo
            product = _productRepository.FindBy(1).FirstOrDefault
            If (product IsNot Nothing) Then
                stockTransfer.Remove(product.StockKeys.Where(Function(x) x.Id = removeRequest.StockTransferID).FirstOrDefault)
            End If

Внутри моей модели StockTransfer я добавил следующий код.

Public Sub Remove(stock As StockKey)
        If (StockTransferContainsAnItemFor(stock)) Then
            StockTransferItems.Remove(GetItemFor(stock))
        End If
    End Sub

    Public Function StockTransferContainsAnItemFor(stock As StockKey) As Boolean
        Return StockTransferItems.Any(Function(x) x.Contains(stock))
    End Function

    Public Function GetItemFor(stock As StockKey) As StockTransferItem
        Return StockTransferItems.Where(Function(x) x.Contains(stock)).FirstOrDefault
    End Function

Но теперь я получаю сообщение об ошибке, говорящее, что внешний ключ равен нулю.

Спасибо.

Майк




Ответы (1)


Если вы хотите удалить элемент, вы можете использовать DbSet.Remove(сущность объекта). DbSet — это свойства вашего DbContext, и вы можете использовать их для удаления элементов.

Что касается вашего второго вопроса, если StockTransfer является совокупным корнем, то StockTransfer должен отвечать за обработку содержащихся в нем элементов. Вам не должно быть разрешено удалять элемент, если об этом не знает общий корень (как еще совокупный корень будет синхронизировать элементы со свойством, таким как TotalStock или что-то в этом роде)

Таким образом, вместо того, чтобы иметь метод Delete для StockTransferItem в вашем репозитории, вы должны иметь метод DeleteTransferItem в своем StockTransfer, а затем передать StockTransfer в функцию Update в вашем репозитории.

person Wouter de Kort♦    schedule 31.01.2012
comment
Спасибо за ваш ответ. Первоначально я пробовал что-то похожее на это, прежде чем я заработал этот пример. Проблема, с которой я столкнулся, заключалась в том, что он жаловался на то, что для внешних ключей установлено значение null. - person user1180223; 31.01.2012
comment
Да, это может быть проблемой. Вероятно, это связано с висящим элементом StockTransferItem. Ваш репозиторий зависит от реализации, вы можете убедиться, что реализация EF удалит StockTransferItem, но это не должно быть чем-то, что вы могли бы открыть для внешнего мира. - person Wouter de Kort♦; 31.01.2012
comment
Я обновил свой OP новым кодом, который я использую. Можете ли вы привести пример удаления StockTransferItem? - person user1180223; 01.02.2012
comment
@user1180223 user1180223 Может быть, вы можете опубликовать новый вопрос с некоторым кодом и точным исключением и где оно возникло? - person Wouter de Kort♦; 02.02.2012