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

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)

Related

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

LINQ Parent class queries db for fields in child class

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.

The navigation property is not a declared property on type. Verify that it has not been explicitly excluded from the model

Usually, for such cases there is a messup in the declaration of Foreign Keys but I have run my eyes over this code countless times.
Manifests and BL are parent-child entities.
Namespace models
Public Class manifest
<DatabaseGenerated(DatabaseGeneratedOption.None)>
<Key>
Public Property id As Integer 'uses SQL sequence and not autogenerated
Public Property arrivalDate As Date
Public Overridable Property BL As IEnumerable(Of bl)
Public Overridable Property Vessel As vessel
end Class
End Namespace
And also
Namespace models
Public Class bl
<DatabaseGenerated(DatabaseGeneratedOption.None)>
<Key> <Column(Order:=2)>
Public Property blid As Integer
<Key> <Column(Order:=1)>
<ForeignKey("manifest")>
Public Property manifestid As Integer
<ForeignKey("manifestid")>
Public Overridable Property manifest As manifest
<Required>
Public Overridable Property container As IEnumerable(Of container)
End Class
End Namespace
But in the end, the outcome is "The navigation property 'BL' is not a declared property on type 'manifest'. Verify that it has not been explicitly excluded from the model and that it is a valid navigation property."
Any hint on what am I missing?

Entity Framework Update Foreign Key constraint may cause multiple cascade paths

I'm working on a project that is using entity framework and I'm getting the following error when I try and update my database.
Introducing FOREIGN KEY constraint 'FK_dbo.VisualManualWebPageFiles_dbo.VisualManualHeaders_VisualManualHeaderID' on table 'VisualManualWebPageFiles' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint.
Here are the classes that are being used for this.
First With a VisualManualHeader class.
<Table("VisualManualHeaders")>
Public Class VisualManualHeader
<Key>
Public Property VisualManualHeaderID As Integer
<Required>
Public Property Name As String
Public Overridable Property VisualManualPages As ICollection(Of VisualManualPage)
Public Overridable Property VisualManualWebPageFiles As ICollection(Of VisualManualWebPageFile)
End Class
Then a VisualManualHeader has the associated VisualManualPages with it like the following.
<Table("VisualManualPages")>
Public Class VisualManualPage
Enum VisualManualPageType
VIDEO
IMAGE
TEXT
WEBPAGE
End Enum
<Key>
Public Property VisualManualPageID As Integer
<Required>
Public Property Title As String
Public Property VisualManualHeaderID As Integer
<ForeignKey("VisualManualHeaderID")>
Public Overridable Property VisualManualHeader As VisualManualHeader
Public Property Content As String
Public Property PageType As VisualManualPageType
Public Overridable Property VisualManualWebPageFiles As ICollection(Of VisualManualWebPageFile)
End Class
The pages can then have many VisualManualWebPageFiles associated to the page.
<Table("VisualManualWebPageFiles")>
Public Class VisualManualWebPageFile
<Key>
Public Property VisualManualWebPageFileID As Integer
<Required>
Public Property VisualManualHeaderID As Integer
<ForeignKey("VisualManualHeaderID")>
Public Overridable Property VisualManualHeader As VisualManualHeader
<Required>
Public Property VisualManualPageID As Integer
<ForeignKey("VisualManualPageID")>
Public Overridable Property VisualManualPage As VisualManualPage
Public Property FileLocation As String
End Class
I have a feeling the problem is in the VisualManualWebPageFiles class due to the foreign key of the VisualManualHeader as if I remove this I can then update my project.
Thanks.
I think the problem lies with the association of the entity classes. Taking a look at your code seems that VisualManualHeader and VisualManualPage are in Many-To-Many relation; i.e. one instance of VisualManualHeader can be associated with many instances of VisualManualPage, and the the reverse is also true.
If that is indeed the case then, the relation between 2 classes are represented in VisualManualWebPageFile correctly and there is no need of keeping unnecessary properties in both VisualManualHeader, and VisualManualPage. I have tried to remove the same as follows:
VisualManualHeader
<Table("VisualManualHeaders")>
Public Class VisualManualHeader
<Key>
Public Property VisualManualHeaderID As Integer
<Required>
Public Property Name As String
Public Overridable Property VisualManualWebPageFiles As ICollection(Of VisualManualWebPageFile)
End Class
VisualManualPage
<Table("VisualManualPages")>
Public Class VisualManualPage
Enum VisualManualPageType
VIDEO
IMAGE
TEXT
WEBPAGE
End Enum
<Key>
Public Property VisualManualPageID As Integer
<Required>
Public Property Title As String
Public Property Content As String
Public Property PageType As VisualManualPageType
Public Overridable Property VisualManualWebPageFiles As ICollection(Of VisualManualWebPageFile)
End Class
VisualManualWebPageFile
<Table("VisualManualWebPageFiles")>
Public Class VisualManualWebPageFile
<Key>
Public Property VisualManualWebPageFileID As Integer
<Required>
Public Property VisualManualHeaderID As Integer
<ForeignKey("VisualManualHeaderID")>
Public Overridable Property VisualManualHeader As VisualManualHeader
<Required>
Public Property VisualManualPageID As Integer
<ForeignKey("VisualManualPageID")>
Public Overridable Property VisualManualPage As VisualManualPage
Public Property FileLocation As String
End Class
You are basically correct. The WebPageFiles does not need a reference to the ManualHeader table - and it actually could cause errors.
Example:
ManualPage ID 10 is owned by ManualHeader 1. You add WebPageFiles ID 15 with ManualPage 1 - but there is nothing stopping you setting WebPageFiles.ManualHeaderID to 3 as long as ManualHeader 3 exists. You now have a WebPageFile which a bit confused about who its grandparent is.
The correct way is to set the parent ID only (ManualPage). This parent will contain the ID of its own parent (ManualHeader) and so the child (WebPageFile) can unambiguously fing its grandparent via its parent.