0

My ultimate aim is to have an EF model working alongside a sqlite local db. The dev is going to involve a lot of modification of the db and thus a lot of updating of the model. The gui will use a lot of Master-Detail views to edit the data.

I've figured that in order to get master-detail views working, you have to replace ICollection and HashSet with ObservableCollection. I achieve this via a custom ObservableListSource class.

I've given up on trying to achieve this via "database first." There's to many limitations/omissions on the "update model from database" option. For example, it doesn't update any changed fields or relationships, meaning you have to delete and re-impot the whole model again. You then have to change the .tt files to change Hashset and ICollection to the ObservableListSource. Overall the method just feels too shonky and hit and miss.

Thus, looked into the "Code first from Database" option. On initial tests appears a lot more robust and reliable than database first. However, it doesn't generate and .tt files, which would allow you to change all of the ICollection entries in the generated classes.

I did find this:

Changing the generated classes from "Code First From Database" EF6

And successfully downloaded the .t4 file. I managed to get HashSet replaced by ObservableListSource by amending some code. Extract of the fuill entity.t4 file:

        Public Sub New()
    <#
        foreach (var collectionProperty in collectionProperties)
        {
    #>
            <#= code.Property(collectionProperty) #> = New ObservableListSource(Of <#= code.Type(collectionProperty.ToEndMember.GetEntityType()) #>)()
    <#
        }
    #>
        End Sub

Now this works..when the classes/entities are generated, the replacement occurs correctly. However, I cannot get the same to work for ICollection. An example of how this in generated in the entity class:

<Table("dbControl")>
Partial Public Class dbControl
    Public Sub New()
        dbController_Controls = New ObservableListSource(Of dbController_Controls)()
    End Sub

    Public Property ID As Long

    <StringLength(2147483647)>
    Public Property Name As String

    Public Property ControlTypeID As Long?

    Public Property ControlAssociationID As Long?

    Public Overridable Property dbControlAssociation As dbControlAssociation

    Public Overridable Property dbControlType As dbControlType

    Public Overridable Property dbController_Controls As ICollection(Of dbController_Controls)
End Class

The relevant part of the EntityType.t4 appears to be:

    foreach (var navigationProperty in entityType.NavigationProperties)
    {
        if (!first)
        {
            WriteLine(string.Empty);
        }
        else
        {
            first = false;
        }
#>
    Public Overridable Property <#= code.Property(navigationProperty) #> As <#= code.Type(navigationProperty) #>
<#
    }
#>
End Class

However, there is no specific reference in the file to ICollection anywhere. Therefore a straight replace doesn't seem to be possible, unlike HashSet

Does anyone have any ideas?

I'm coming close to ditching Entity Framework all together tbh, as it's proving to be a little temperamental/infuriating! Any help appreciated

stigzler
  • 793
  • 2
  • 12
  • 29
  • ObservableCollection is an ICollection, so do you really need to change the property type in addition to replacing the HashSet with a different collection type? – David Browne - Microsoft Oct 30 '18 at 22:11
  • Thanks David, but from the research I've done, in order to get master-detail record sets working, you have to change this. One exmaple here: https://learn.microsoft.com/en-gb/ef/ef6/fundamentals/databinding/wpf – stigzler Oct 31 '18 at 07:46

0 Answers0