I am building a repository for a new application which uses Entity Framework 5 as the backend data source. I have the basic CRUD operation working for simple models but I am struggling to understand how to update related objects on an update to an exising object.
Model
Imports System Imports System.Collections.Generic
Partial Public Class tblUser
Public Property idUser As Integer
Public Property username As String
Public Property pwd As String
Public Overridable Property tblUsermmRoles As ICollection(Of tblUsermmRole) = New HashSet(Of tblUsermmRole)
End Class
Imports System
Imports System.Collections.Generic
Partial Public Class tblUsermmRole
Public Property idUser As Integer
Public Property idRole As Integer
Public Overridable Property tblUser As tblUser
Public Overridable Property tblUserRole As tblUserRole
End Class
I am trying to add records to the tblUsermmRole object against a related tblUser record but I can't get the update to work.
POCO
Public Class User
Public Property ID As Int32
Public Property Username As String
Public Property Password As String
Public Property AccessRoles As IEnumerable(Of Int32)
Public Sub New()
End Sub
Public Sub New(id As Int32, userName As String, password As String, roles As List(Of Int32))
Me.ID = id
Me.Username = userName
Me.Password = password
Me.AccessRoles = roles
End Sub
End Class
Public Class UserRoles
Public Property RoleID As Int32
Public Sub New(roleID As Int32)
Me.RoleID = roleID
End Sub
End Class
Repository
Imports System.Data.Entity
Namespace DataAccess.Repository
Public MustInherit Class EntityFramworkContextBase
Inherits DbContext
Implements IUnitOfWork
Public Sub New(entityConnectionStringOrName As String)
MyBase.New(entityConnectionStringOrName)
End Sub
Public Sub Add(Of T As Class)(obj As T) Implements IUnitOfWork.Add
[Set](Of T).Add(obj)
End Sub
Public Sub Attach(Of T As Class)(obj As T) Implements IUnitOfWork.Attach
Dim entity As T
If ExistsInContext(obj) Then
entity = ObjectInContext(obj)
Entry(entity).CurrentValues.SetValues(obj)
Else
entity = [Set](Of T).Attach(obj)
End If
Entry(entity).State = EntityState.Modified
End Sub
Public Sub Commit() Implements IUnitOfWork.Commit
MyBase.SaveChanges()
End Sub
Public Function [Get](Of T As Class)() As IQueryable(Of T) Implements IUnitOfWork.Get
Return [Set](Of T)()
End Function
Public Function Remove(Of T As Class)(obj As T) As Boolean Implements IUnitOfWork.Remove
Dim entity As T
If ExistsInContext(obj) Then
entity = ObjectInContext(obj)
Else
entity = [Set](Of T).Attach(obj)
End If
[Set](Of T).Remove(entity)
Return True
End Function
Private Function ExistsInContext(Of T As Class)(obj As T) As Boolean
Return [Set](Of T).Local.Any(Function(o) o.Equals(obj))
End Function
Private Function ObjectInContext(Of T As Class)(obj As T) As T
Return [Set](Of T).Local.FirstOrDefault(Function(o) o.Equals(obj))
End Function
End Class
End Namespace
Problem
When calling the Entry(entity).CurrentValues.SetValues(obj)
line in the Attach
method the basic properties are copied over but the new elements for the tblUsermmRole object are not.
New Object with updated
Entity after SetValues
From initial research it looks like the SetValues
method does not copy over related navigation properties as discussed in this post
Question
Given the repository pattern ( plus the UnitOfWork pattern) that I am using how do you maintain the object graph relationships and update the database?
Additional note
This method works as expected for new instances of the tblUsers object with attached tblUsermmRoles. Records for both tables are added maintaining foreign keys.