LINQ Parent class queries db for fields in child class - vb.net

I'm using EF 6.1.3 and .NET framework 4.5.2
I'm updating code which uses two classes:
Public Class Holder
<Key(), Column(Order:=0)>
Property Holder_No As Integer?
<Key(), Column(Order:=1)>
Property Title_No As Integer?
Property Family_Name As String
Property Given_Name_1 As String
Property Given_Name_2 As String
End Class
Public Class OwnerChange
Inherits Holder
Public Property Change_Type As String
Public Property Change_Date As Date
Public Property Process_Date As Date?
End Class
The Holder class is a 1:1 mapping with a table in the db.
The DbContext only creates a dbSet for the Holder class.
Public Property Holder As DbSet(Of Holder)
When I create a simple query to access data from the holder table in the db, I get column errors for change_type, change_date and process_date.
Using contextdb = New userContext()
Dim att1 = (From b In contextdb.Holder
Select b).Take(10)
End Using
The query seems to think I'm trying to query the parent table for the child class' information.
Why does LINQ request the child's columns from the parent class' table in the database? Do I need to do something to specify that I only want to retrieve the holder information?

The Entity Framework apparently creates a hierarchy whenever one class is inherited from another. So, when I was querying for the holder record, it was looking in the holder table for the elements from the OwnerChange class.
What I needed to do was take the holder class and turn it into an abstract class, then inherit it into the two classes I want to access different tables in the database.
Public MustInherit Class base_class
<Key(), Column(Order:=0)>
Property Holder_No As Integer?
<Key(), Column(Order:=1)>
Property Title_No As Integer?
Property Family_Name As String
Property Given_Name_1 As String
Property Given_Name_2 As String
End Class
Public Class OwnerChange
Inherits base_class
Public Property Change_Type As String
Public Property Change_Date As Date
Public Property Process_Date As Date?
End Class
Public Class holder
Inherits base_class
End Class
Changing the class hierarchy ultimately solved the problem.

Related

How to link a view to a model in vb.net code First

I've an old programm with edmx. Inside this one, I've linked a class (Table) To a View (Table/filter on a value of a column)
I want migrate this project to code first.
I copy/paste the project delete edmx file and generate models from an existing database.
All is good except this link.
<Table("JoinAffectation")>
partial public Class JointAffectation
public property Id as Long
public IdRecherche as Integer 'the link with my view
<NotMapped>
<ForeignKey("Id")>
PUBLIC OVERRIDABLE PROperty RechercheJoint as ViewRechercheJoint
But When I try to use function of automatical sort/filter using expression
I've error : The specified type member 'RechercheJoint' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
If I removed I error saying I don't same comumn and property... Also , How Can I stipulate RechercheJoint is mapped on IdRecherche
thanks for your help
Finally Using modelbuilder, I can join my view and my table like in edmx
<Table("JointAffectation")>
Partial Public Class JointAffectation
Public Property Id As Long
Public Property IdTypeJoint As Long
Public Property IdRecherche As Integer
Public Overridable Property JointType As JointType
<ForeignKey("Id")>
Public Overridable Property RechercheJoint As ViewRechercheJoint
End Class
<Table("ViewRechercheJoint")>
Partial Public Class ViewRechercheJoint
<Key>
<DatabaseGenerated(DatabaseGeneratedOption.None)>
Public Property Id As Integer
<StringLength(50)>
Public Property Libelle As String
<ForeignKey("IdRecherche")>
Public Overridable Property JointAffectations As ICollection(Of JointAffectation)
End Class
modelBuilder.Entity(Of JointAffectation)() _
.HasRequired(Function(e) e.RechercheJoint) _
.WithMany(Function(e) e.JointAffectations) _
.HasForeignKey(Function(e) e.IdRecherche)

Repeater control with strongly typed objects entity framework

I am new to entity framework, and wondered if someone could help. I have 2 classes that define documents and then their versions (1 to many relationship).
I am using the asp:repeater to display the list of documents, but cannot access information re the versions.
The 2 classes are below
Public Class Document
<Key>
Public Property ID As Guid
Public Property Name As String
Public Property Description As String
Public Property CreationDate As Date
Public Property ReviewDate As Date
Public Property NextReview As Date
Public Overridable Property Versions As ICollection(Of DocumentVersion)
End Class
Public Class DocumentVersion
<Key>
Public Property VersionID As Guid
<ForeignKey("Document")>
Public Property DocumentID As Guid
Public Property FilePath As String
Public Property CreationDate As Date
Public Overridable Property Document As Document
End Class
In the asp:repeater I'm using <%#: Item.Name %> to display the document name, but cannot access <%#: Item.Versions.FilePath %> for example.
If I do include item.versions.filepath I get the error:
BC30456: 'FilePath' is not a member of 'ICollection(Of DocumentVersion)'.
Any help would be very appreciated.

In EF how do I code the class to access the foreign key?

EF 6, code first technique.
Two classes defined as:
Public Class SqlLayerTypeSet
Public Overridable Property SqlLayerTypeSetID As Integer
Public Overridable Property Name As String
Public Overridable Property Desc As String
Public Property ConferenceTypes As New List(Of SqlConferenceType)
End Class
Public Class SqlConferenceType
Public Property ID As Integer
Public Property Name As String
Public Property Desc As String
End Class
After seeding the tables look, respectively, as this:
What do I add to Class SqlConferenceType so I can access the existing foreign key SqlLayerTypeSet_SqlLayerTypeSetID which points back to the SqlLayerTypeSet that SqlConferenceType is a member of.
When I add whatever it is supposed to be, will that require a new migration?
I had thought that EF allows you to define properties in the class using a convention that simply gives you access to the foreign key but doesn't actually change the table definition. The way I have been trying to add a property to the class is actually adding another column in the table when all I really want to do is access the column that EF code first already created.
I know this is a basic question, but I just can't seem to find the right SO post that explains it to me.
Added after initial post:
This is the line I added that adds access to the parent:
Public Overridable Property SqlLayerTypeSet As SqlLayerTypeSet
But if I try to add a specific property for the parent's key such as:
Public Property SqlLayerTypeSetID as Integer
That creates the extra column. Is it the case that the only property I can add to Class SqlConferencetype is the navigation property, and I simple have to retrieve the foreign key value using navigation as opposed to being able to define a property that simply holds the foreign key value?
Public Class SqlLayerTypeSet
Public Overridable Property SqlLayerTypeSetID As Integer
Public Overridable Property Name As String
Public Overridable Property Desc As String
<ForeignKey("SqlConferenceType")>
Public Overridable Property SqlConferenceTypeID as Integer 'Foreign key property
Public Overridable Property ConferenceTypes As New List(Of SqlConferenceType) 'Relationship property
End Class
Public Class SqlConferenceType
Public Property ID As Integer
Public Property Name As String
Public Property Desc As String
Public Overridable Property SqlLayerTypeSet as SqlLayerTypeSet 'Relationship property
End Class

Entity Framework load related objects without available navigation property (DTO)?

I have some objects in EF using model first, most of the objects are related:
Partial Public Class PersonLog
Public Property Id As System.Guid
Public Property ExternalEmailGuid As System.Guid
Public Overridable Property Person As Person
End Class
Partial Public Class EmailIn
Public Property Id As System.Guid
Public Property PersonID As System.Guid
End Class
Partial Public Class EmailOut
Public Property Id As System.Guid
Public Property PersonID As System.Guid
End Class
Such that working with a Person object i can easily grab the associated PersonLogs
_person.PersonLogs.OrderByDescending(Function(c) c.CreateDate).ToList()
However i need to grab the associated EmailIn or EmailOut objects associated with that PersonLog. No association was added between them and i'm not quite sure why.
Is there a way to load all of the associated EmailIn & EmailOut objects without iterating through each PersonLog item and performing a lookup? The relationship between PersonLog and EmailIn or EmailOut is 1:1
The approach I was considering was creating a new class that takes the current context and PersonLog as constructors and has public properties PersonLog, EmailIn and EmailOut, like this:
Public Class PersonLogDTO
Public Sub New(obj As PersonLog, cxt As DB.DBContainer)
_obj = obj
_cxt = cxt
End Sub
Public ReadOnly Property LeadLog As PersonLog
Get
Return _obj
End Get
End Property
Public ReadOnly Property EmailOut As EmailOut
Get
Return _cxt.EmailOut.Find(_obj.ExternalEmailGuid)
End Get
End Property
Got to be a better way, right?

Entity Framework Core - Audit

Is there a way to write an Audit log automatically?
I have created a DbSet(Of Protocols)
Here is my protocol class:
Public Class Protocol
Inherits ModelBase
Implements ILogicalTimestamp
<Key>
Public Property ProtocolId As Integer
<Required>
Public Property ProtocolText As String
Public Property CreatedByUserId As Integer?
<Required>
Public Property CreatedByUser As User
<Required>
<DefaultValue(0)>
Public Property Type As ProtocolType
Public Property LinkedToUserId As Integer?
Public Property LinkedToUser As User
Public Property LinkedToBusinessPartnerId As Integer?
Public Property LinkedToBusinessPartner As BusinessPartner
Public Property LinkedToClientId As Integer?
Public Property LinkedToClient As Client
Public Property LinkedToSettingId As Integer?
Public Property LinkedToSetting As Setting
Public Property LastUpdateTimestamp As Date? Implements ILogicalTimestamp.LastUpdateTimestamp
Public Property CreationTimestamp As Date? Implements ILogicalTimestamp.CreationTimestamp
Public Enum ProtocolType
AutoChanges = 0
Explicitly = 1
End Enum
End Class
How can i write changes in protocol?
And how can i get the current UserId into the SaveChanges method to fill CreatedByUserId property in my protocol class?
Maybe anyone has an idea to do that automatically.
You can create a custom DB Context inheriting from DbContext, and then override the SaveChanges() method, so you can manipulate the data before/after modification.
Or you can use a library like Audit.EntityFramework, or check its code (C# sorry).
Also the library EntityFramework-Plus can probably help.