EntityFramework 6 - Transient.collection Exception - asp.net

I have the below Database-First model:
Imports System
Imports System.Collections.Generic
Partial Public Class User
Public Property ID As Integer
Public Property Username As String
Public Property Password As String
Public Property IsDisabled As Boolean
Public Property IsSuper As Boolean
Public Property MustChangePassword As Boolean
Public Property Notes As String
Public Overridable Property UserPermissions As ICollection(Of UserPermission) = New HashSet(Of UserPermission)
End Class
And the DB Context
Partial Public Class Entities
Inherits DbContext
Public Sub New()
MyBase.New("name=Entities")
End Sub
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
Throw New UnintentionalCodeFirstException()
End Sub
.
.
.
Public Overridable Property Users() As DbSet(Of User)
.
.
.
End Class
Whenever I run the below query:
dim ent = New Entities()
result = (From u In ent.Users
Where u.ID = ID
Select u).SingleOrDefault()
I get the following error:
'Users' is not a member of 'Transient.collection[Conso_Model.Entity(Nullable=True,DefaultValue=)]'. To extract a property of a collection element, use a sub-query to iterate over the collection. Near escaped identifier, line 1, column 12.
Any clue?

Found the problem!
There is another EF class named Entity with pluralized collection name 'Entities' (similar to Database Context class)!
How stupid VB compiler didn't fire any warning about this!

Related

Cannot insert the value NULL into column 'Discriminator', table 'AspNetUsers' after modifying ApplicationUser

I have modified my ApplicationUser to include several fields needed for my application. I also set the context that stores the other objects in the Entity Framework to use IdentityDbContext as well so they could share the same database. Everything is going fine, however when I go to create a user an exception is thrown:
Cannot insert the value NULL into column 'Discriminator', table 'AspNetUsers'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Here is my IdentityModels:
Public Class ApplicationUser
Inherits IdentityUser
Public Property FirstName As String
Public Property LastName As String
Public Property OfficePhone As String
Public Property MobilePhone As String
Public Property Administrator As Boolean
Public Property Notifications As Boolean
My ApplicationDbContext :
Public Class ApplicationDbContext
Inherits IdentityDbContext(Of ApplicationUser)
Public Sub New()
MyBase.New("ExpressConnection", throwIfV1Schema:=False)
End Sub
Public Shared Function Create() As ApplicationDbContext
Return New ApplicationDbContext()
End Function
End Class
Here is my context:
Public Class MyContext
Inherits IdentityDbContext
Public Sub New()
MyBase.New("DefaultConnection")
End Sub
Public Property Clients As DbSet(Of Client)
Public Property Employees As DbSet(Of ApplicationUser)
Public Property Invoices As DbSet(Of Invoice)
End Class
Here is the code to create a new user:
Create a UserManager object based on the UserStore object and the ApplicationDbContext object.
Dim userMgr As New UserManager(Of ApplicationUser)(New UserStore(Of ApplicationUser)(context))
Dim appUser As New ApplicationUser
appUser.UserName = "user#example.com"
appUser.Email = "user#example.com"
IdUserResult = userMgr.Create(appUser, "$password$")
The database is dropped every time the application starts so the initial migration should handle the changes to ApplicationUser. I'm not sure why when I go to create a new user the application fails with the above exception.

Assigning one Table ID to another Table ID Like Asp.Net Identity AspNetUserRole

Hi i have 3 model class setup Group
Public Class Group
Public Property Id As Long
Public Property Name As String
Public Property CoverImgUrl As String
Public Overridable ReadOnly Property Profile() As ICollection(Of Profile)
Get
End Get
End Property
End Class
Profile
Public Class Profile
Public Property Id As Long
<Required>
<MaxLength(20)>
<Display(Name:="First Name")>
Public Property FirstName As String
<Required>
<MaxLength(20)>
<Display(Name:="Last Name")>
Public Property LastName As String
Public Overridable ReadOnly Property Group() As ICollection(Of Group)
Get
End Get
End Property
and GroupMembers.
Public Class GroupMembers
Public Sub New()
End Sub
Public Overridable Property Group() As Group
Public Overridable Property GroupId() As String
Public Overridable Property Profile() As Profile
Public Overridable Property ProfileId() As String
End Class
i ran the Update-Database command which updated my database and created a table ProfileGroup like asp.net AspNetUserRole.
With the progress so far how can i assign one group to a profile i created like asp.net uses the UserManager.AddToRole method to assign a user to a role or any global best practice to this. Thanks
It looks like you're just trying to set up a many-to-many relationship between Profile and Group. However, you're going about it all wrong.
First, traditionally, you don't actually define a class for the intermediary table, GroupMembers in this case, unless you need a payload, i.e. additional data on the relationship. In your posted code, there's no payload on the relationship, so you're just making your life more difficult this way. Assuming you wanted to keep things as they are, though, you would need to set up your classes like:
Public Class Group
...
Public Overridable Property Profiles As ICollection(Of GroupMember)
End Class
Public Class Profile
...
Public Overridable Property Groups As ICollection(Of GroupMember)
End Class
Public Class GroupMember
Public Property GroupId As String
Public Overridable Property Group As Group
Public Property ProfileId As String
Public Overridable Property Profile As Profile
End Class
This will then be enough for Entity Framework to discern the relationships and create the appropriate tables with the appropriate foreign keys. However, you would be forced to access the Profile/Group indirectly, i.e. profile.Groups.First().Group. Whereas, with an implicit join table, you could just do profile.Groups.First().
So, in order to have an implicit join table, you would just need the following classes:
Public Class Group
...
Public Overridable Property Profiles As ICollection(Of Profile)
End Class
Public Class Profile
...
Public Overridable Property Groups As ICollection(Of Group)
End Class
Notice that the GroupMember class goes away completely. Entity Framework will still see this as a many-to-many and create a table, most likely named dbo.GroupProfiles. If you're not happy with the table name, you can declare it using fluent configuration:
modelBuilder.Entity(Of Profile)().
HasMany(Function(t) t.Groups).
WithMany(Function(t) t.Profiles).
Map(Sub(m)
m.ToTable("GroupMembers")
End Sub)

generate dropdown using values from another table in asp.net. vb mvc 4

I have created model class and controller related to a database table and want to populate a dropdown list from another table. my model and controller code is below:-
Imports System.Data.Entity
Namespace employee1
Public Class EmployeeController
Inherits System.Web.Mvc.Controller
Private db As New EmployeeDBContext
'
' GET: /Employee/
Function Index(ByVal sortOrder As String) As ActionResult
ViewBag.LastNameSortParm = If(String.IsNullOrEmpty(sortOrder), "LastName_desc", String.Empty)
Dim Employee = From e In db.Employee Select e
Select Case sortOrder
Case "LastName_desc"
Employee = Employee.OrderByDescending(Function(e) e.LastName)
Case Else
Employee = Employee.OrderBy(Function(e) e.LastName)
End Select
Return View(Employee.ToList())
End Function
'
' GET: /Employee/Details/5
Function Details(Optional ByVal id As Integer = Nothing) As ActionResult
Dim employeemodel As EmployeeModel = db.Employee.Find(id)
If IsNothing(employeemodel) Then
Return HttpNotFound()
End If
Return View(employeemodel)
End Function
'
' GET: /Employee/Create
Function Create() As ActionResult
Return View()
End Function
and this is my model
Imports System.Data.Entity
Public Class EmployeeModel
Public Property ID() As Integer
Public Property CompanyCode() As String
Public Property FirstName() As String
Public Property LastName() As String
Public Property DeptNum() As String
Public Property Status() As Char
Public Property txtCity() As String
Public Property txtState() As String
Public Property txtZip() As String
Public Property txtPhone() As String
Public Property txtPhoneExt() As String
Public Property LastReviewDate() As Date
Public Property HireDate() As Date
End Class
Public Class EmployeeDBContext
Inherits DbContext
Public Property Employee() As DbSet(Of EmployeeModel)
End Class
I want a dropdown list in create view for status from another table named IDStatus view is like
#Using Html.BeginForm()
#Html.ValidationSummary(True)
#<fieldset>
<legend>EmployeeModel</legend>
<div class="editor-label">
#Html.LabelFor(Function(model) model.CompanyCode)
</div>
<div class="editor-field">
#Html.EditorFor(Function(model) model.CompanyCode)
#Html.ValidationMessageFor
</div>
<!-- how do i use dropdown list here which is from different table?-->
</fieldset>
End Using
Either you can add one more property as a collection of the same model, or you can fill that collection in a ViewBage and use it the same at your view.
At Controller
ViewBag.DropDownCollection = "Collection"
At View
#Html.DropDownList("dropDownName",ViewBag.DropDownCollection)
Fiddle
create viewmodel and pass both table properties in that
public class viewmodel
{
public table1 Table1{get;set;} //return your first table properties here
public table2 Table2{get;set;} //return your second table properties here
}
In view
#htnl.dropdownlistfor(m=>m.Table2.propertyname,-----)`enter code here`

Entity Framework - Insert a many-to-many relationship from a FormView

I have two entities linked with an association entity. In code I can easily insert one, or all of these at once. But, on the front end, I am using FormViews to allow the user to enter data. When I insert an address, how do I let it know to insert a facility at the same time, unless I have the facility and the address on the same formview?
Public Class facility
<Key()> _
Public Property facility_id As Integer
Public Property facility_present_use As String
Public Property facility_prior_use As String
Public Property facility_occupied As Boolean
Public Property facility_size As Double
Public Property facility_floors As Integer
Public Property facility_age As Integer
Public Property facility_single_residence As Boolean
Public Property facility_number_of_units As Integer
Public Overridable Property facility_address As ICollection(Of facility_address) = New HashSet(Of facility_address)
End Class
Public Class address
<Key()> _
Public Property address_id As Integer
Public Property address_name As String
Public Property address_address_1 As String
Public Property address_address_2 As String
Public Property address_city As String
Public Property address_state As Integer?
Public Property address_zip As String
Public Property address_contact_first_name As String
Public Property address_contact_last_name As String
Public Property address_phone_area As String
Public Property address_phone As String
Public Overridable Property lu_state As lu_state
Public Overridable Property facility_address As ICollection(Of facility_address) = New HashSet(Of facility_address)
End Class
Public Class facility_address
<Key()> _
Public Property facility_address_id As Integer
Public Property address_type As Integer
Public Property facility_id As Integer
Public Property address_id As Integer
Public Overridable Property lu_address_type As lu_address_type
Public Overridable Property facility As facility
Public Overridable Property address As address
End Class

Why is my class nothing?

I have a .NET 2010 project. In it, I create a basic user class. Instantiate it and successfully fill it with data. The entire time it is doing this, if I hover over the class, it says it is nothing, even as it fills its properties. Later on, it hoses me in the UI, even though the property has a value it says the class is nothing.
I DO instatiate the class...
Dim oExtendedUser As New ExtendedUser
and here is the classs definition...
Public Class ExtendedUser
Inherits System.Web.Security.MembershipUser
Public Sub New()
_Role = New Role
End Sub
Public Property ExtendedUserID As Int32
Public Property FirstName As String
Public Property LastName As String
Public Property Phone As String
Public Property UserID As Guid
Public Property Role As Role
Public Property UserName() As String
Public Property Password() As String
Public Property SecurityQuestion() As String
Public Property SecurityAnswer() As String
End Class
I changed the class. I added MyBase.New() but the problem persists. On the UI, here is the code that executes when the button is clicked. Director has, as a proprety, ExtendedUSer
Dim oCase As New BE.Case
Dim oDirector As New BE.Director
oDirector = SessionManager.Director 'the values are here
oCase.Investigator.ExtendedUserID = oDirector.ExtendedUser.ExtendedUserID
And here is the Director...
Public Class Director
Public Sub New()
_ExtendedUser = New ExtendedUser
End Sub
Public Property ID As Int32
Public Property ExtendedUser As ExtendedUser
End Class
You got tricked by the ToString Override.
Your object exists but it overrides the ToString Method : MembershipUser.ToString
To validate this behavior, try it with a simple class :
VB.NET
Public Class Test
Public Property TestString As String
Public Overrides Function ToString() As String
Return Me.TestString
End Function
End Class
C#
public class Test
{
public string TestString { get; set; }
public override string ToString()
{
return this.TestString;
}
}
With this code, the Watch will show you an instanciated Test to Nothing, because ToString value will be Nothing. The object exist, but Visual Studio is using the ToString Method to populate the value field, and at this point it is Nothing.
VB.NET
Public Class Test
Public Property TestString As String = ""
Public Overrides Function ToString() As String
Return Me.TestString
End Function
End Class
C#
public class Test
{
public Test()
{
this.TestString = "";
}
public string TestString { get; set; }
public override string ToString()
{
return this.TestString;
}
}
With this code you'll get an empty string.
To get back to your code, you cannot extend the MembershipUser so simply, you have to follow this guideline : How to: Implement a Custom Membership User. As many things won't work with your actual extension (For example, your username shadowing the base one).
See this question as well. There are easier ways to extend your user "entity" than inheritance.

Resources