Entity Framework: Metadata when Entity Name is Same as Property? - asp.net

I have a EDM with a entity "Extensions" - within this object is the property extension. I've wired up all the other columns just fine, but this one refuses to wire up. I'm guessing because the entity and the property share the same name?
Here is my code, the extensions doesn't work, the prefix does work:
Imports System.Web.DynamicData
Imports System.ComponentModel.DataAnnotations
<MetadataType(GetType(ExtensionsMetaData))> _
Partial Public Class Extensions
End Class
Public Class ExtensionsMetaData
Private _phones_extensions As Object
Private _prefix As Object
Private _did_flag As Object
Private _len As Object
Private _sfc_id As Object
Private _name_display As Object
Private _floor As Object
Private _room As Object
Private _phones_departments As Object
Private _phones_buildings As Object
Private _phones_phones As Object
Private _phones_restriction_classes As Object
Private _phones_tens As Object
<DisplayName("Extension")> _
Public Property extensions() As Object
Get
Return _phones_extensions
End Get
Set(ByVal value As Object)
_phones_extensions = value
End Set
End Property
<DisplayName("Prefix")> _
Public Property prefix As Object
Get
Return _prefix
End Get
Set(ByVal value As Object)
_prefix = value
End Set
End Property
End Class
How can I get this code to work? I've looked all through my data model and it looks like the name should be Extensions!
The error I am receiving is: The associated metadata type for type 'phoneDBentities.Extensions' contains the following unknown properties or fields: extensions. Please make sure that the names of these members match the names of the properties on the main type.

This is a limitation of EF's "convention over configuration" feature.
Here's a related question: Entity Framework Mapping Oddity - member names cannot be the same as their enclosing type
The easiest way to fix the problem would be to rename the property to "PhoneExtension."

Related

Checking if two lists of objects are equal

I need to compare the values of two lists of objects in VB.NET in a web application. I can't seem to find any working examples of how to do this.
I have tried the example here: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=netframework-4.0
Where they implement a custom interface for doing so. But even using the exact code gives me errors.
Here is the code I'm currently trying. It's basically the same thing as Microsoft's example but using my own class:
Public Class ForumWithName
Inherits IEquatable(Of ForumWithName)
Private mForumID As Integer
Public Property ForumID() As Integer
Get
Return mForumID
End Get
Set(value As Integer)
mForumID = value
End Set
End Property
Private mForumName As String
Public Property ForumName As String
Get
Return mForumName
End Get
Set(value As String)
mForumName = value
End Set
End Property
Private mSubscribed As Boolean
Public Property Subscribed As Boolean
Get
Return mSubscribed
End Get
Set(value As Boolean)
mSubscribed = value
End Set
End Property
Public Function Compare(ByVal other As ForumWithName) As Boolean
If other Is Nothing Then Return False
Return Me.ForumID = other.ForumID AndAlso Me.Subscribed = other.Subscribed
End Function
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Return Compare(TryCast(obj, ForumWithName))
End Function
Public Overrides Function GetHashCode() As Integer
Return (ForumID, Subscribed).GetHashCode()
End Function
End Class
This code fails to compile because of a few errors:
"Classes can inherit only from other classes"
"Predefined type 'ValueTuple(Of,) is not defined or imported."
"Visual Basic 10.0 does not support tuples"
"'GetHashCode' is not a member of '(ForumID as Integer, Subscribed as Boolean)'"
Once I get this code to work, my plan is to compare two lists of the "ForumWithName" class above.
For example(assume SubscribedsForum1 and SubscribedForums2 are both Lists(Of ForumWithName)):
If SubscribedForums1.SequenceEqual(SubscribedForums2) Then
Return True
Else
Return False
End If
IEquatable is an Interface, it needs to be Implemented and not inherited. (I am guessing here, but I think it's a Typo in the MSDN page you linked)
Change the class declare from:
Public Class ForumWithName
Inherits IEquatable(Of ForumWithName)
to be
Public Class ForumWithName
Implements IEquatable(Of ForumWithName)
Once you have done that, you will also need to add this function
Public Overloads Function Equals(other As ForumWithName) As Boolean Implements IEquatable(Of ForumWithName).Equals
Return Compare(TryCast(other, ForumWithName))
End Function
To work around the problem of not being able to use Tuples, you should be able to use this:
Public Overrides Function GetHashCode() As Integer
Return (ForumID & Subscribed).GetHashCode()
End Function
EDIT:
On a side note, you may want to include the properties ForumName and Subscribed in the GetHashCode function to check if the objects are truly equal to one another.

ASP.NET Web API - Return Object - Property Missing

I'm using ASP.NET Web API to return a custom class object. The class has several properties, one of which takes an optional parameter. All the properties except the one with the optional parameter are available in the resulting JSON response. If I remove the optional parameter the other property is then available as well. Any way to return the other property with the optional parameter in place? Thanks!
Here is the specific property I'm having trouble with:
Public Class customer
...
Public ReadOnly Property photoSrc(Optional shape As String = Nothing) As String
Get
Dim srcString = "/Images/User.png"
If shape = "square" Then
srcString = "/Images/UserSquare.png"
End If
Return srcString
End Get
End Property
...
End Class
And here is the api controller function I'm using to return json:
Public Function GetCustomer(id As Integer) As Object
Dim customer As customer = New customer(id)
Return customer
End Function
A property with a parameter is called an indexed property, or indexer. By design, Json.Net (which is used by Web API for JSON serialization) does not serialize indexed properties, even if the index parameter is optional. (You can see this for yourself in the source code for the GetSerializableMembers method of the DefaultContractResolver class.)
The simplest workaround is to add a separate non-indexed property to your class which calls the indexer with the parameter value you want it to have when serialized. You can make the property private if you want; if you do, you just need to mark it with a <JsonProperty> attribute to allow the serializer to "see" it. You can also use this attribute to give the alternate property the same name in the JSON as the indexed property it is replacing.
Public Class Customer
...
<JsonProperty("photoSrc")>
Private ReadOnly Property defaultPhotoSrc As String
Get
Return photoSrc()
End Get
End Property
Public ReadOnly Property photoSrc(Optional shape As String = Nothing) As String
Get
Dim srcString = "/Images/User.png"
If shape = "square" Then
srcString = "/Images/UserSquare.png"
End If
Return srcString
End Get
End Property
...
End Class
Fiddle: https://dotnetfiddle.net/ffNs9D

VB.NET Entity Framework issue with WHERE clause and Boolean values

I'm pretty new to MVC and the Entity Framework, but I'm sure this should be straight forward. I've got a class with a boolean "Active" flag. I then have a function that returns the results by date descending. All I want to do is ensure that only active records are returned. Should be simple, but it fails with the following error:
Error 13 Overload resolution failed because no accessible 'Where' can be called with these arguments:
Extension method 'Public Function Where(predicate As System.Func(Of Review, Integer, Boolean)) As System.Collections.Generic.IEnumerable(Of Review)' defined in 'System.Linq.Enumerable': Value of type 'Boolean' cannot be converted to 'System.Func(Of PowellCasting.Models.Review, Integer, Boolean)'.
Extension method 'Public Function Where(predicate As System.Func(Of Review, Boolean)) As System.Collections.Generic.IEnumerable(Of Review)' defined in 'System.Linq.Enumerable': Value of type 'Boolean' cannot be converted to 'System.Func(Of PowellCasting.Models.Review, Boolean)'.
Extension method 'Public Function Where(predicate As System.Linq.Expressions.Expression(Of System.Func(Of Review, Integer, Boolean))) As System.Linq.IQueryable(Of Review)' defined in 'System.Linq.Queryable': Value of type 'Boolean' cannot be converted to 'System.Linq.Expressions.Expression(Of System.Func(Of PowellCasting.Models.Review, Integer, Boolean))'.
Extension method 'Public Function Where(predicate As System.Linq.Expressions.Expression(Of System.Func(Of Review, Boolean))) As System.Linq.IQueryable(Of Review)' defined in 'System.Linq.Queryable': Value of type 'Boolean' cannot be converted to 'System.Linq.Expressions.Expression(Of System.Func(Of PowellCasting.Models.Review, Boolean))'. C:\Web Projects\Powell Casting\PowellCasting\PowellCasting\Models\Review.vb 42 14 PowellCasting
It looks as thought it doesn't like comparing Booleans but they have the same data type. I'm sure this should be simple, but would appreciate some help. Please see my code below.
Public Class Review
Private PowellCastingDB As PowellCastingEntites = New PowellCastingEntites
<ScaffoldColumn(False)>
Public Property ReviewID As Integer
<Required(ErrorMessage:="An review title is required")>
<StringLength(256)>
<DisplayName("Title")>
Public Property Title As String
<DisplayName("Heading")>
Public Property Heading As String
<DisplayName("ReviewText")>
<StringLength(4096)>
Public Property ReviewText As String
<DisplayName("Author")>
<StringLength(256)>
Public Property Author As String
<DisplayName("Publication")>
<StringLength(150)>
Public Property Publication As String
<DisplayName("PublicationDate")>
Public Property PublicationDate As Date
<DisplayName("PublicationLink")>
<StringLength(1000)>
Public Property PublicationLink As String
<DisplayName("Image")>
<StringLength(512)>
Public Property Image As String
<DisplayName("Active")>
Public Property Active As Boolean
Public Property Reviews As List(Of Review)
Public Function GetLatestReviews(ByVal count As Integer) As List(Of Review)
Return PowellCastingDB.Reviews.Where(Active = True).
OrderByDescending(Function(a) a.PublicationDate).
Take(count).
ToList()
End Function
End Class
End Namespace
You need to specify a lambda expression:
Return PowellCastingDB.Reviews.Where(Function(x) x.Active = True).
(rest of query)
Or just:
Return PowellCastingDB.Reviews.Where(Function(x) x.Active).
(rest of query)
Try this:
Return PowellCastingDB.Reviews.Where(Function(review) review.Active = True)

fluent nhibernate Exception error

am trying to implement fluent nhibernate in MVC project...there were no build errors... but when i run the project i get this exception
System.Xml.Schema.XmlSchemaValidationException: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has incomplete content. List of possible elements expected: 'meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id' in namespace 'urn:nhibernate-mapping-2.2'.
have no idea what am doing wrong here... the following is the code for opening session factory...
Private Function CreateSessionFactory() As ISessionFactory
Dim sessionFactoryObject As ISessionFactory
sessionFactoryObject = Fluently.Configure().Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005.ConnectionString("Data Source=.\sqlexpress;Initial Catalog=Designs;User ID=sa;Password=root")).Mappings(Function(x) x.FluentMappings.Add(GetType(DesignMap))).BuildSessionFactory()
Return sessionFactoryObject
End Function
this is really driving me nuts....thanks in advance...:)
update-the mappings
the design table map
Public Class DesignMap
Inherits ClassMap(Of Design)
Public Sub DesignMap()
Table("DesignList")
Id(Function(x) x.DesignId)
Map(Function(x) x.DesignType)
References(Function(x) x.Designer, "DesignerId")
End Sub
End Class
the designer table map
Public Class DesignerMap
Inherits ClassMap(Of Designer)
Public Sub DesignerMap()
Table("DesignerList")
Id(Function(x) x.DesignerId)
Map(Function(x) x.DesignerName)
Map(Function(x) x.DesignerCompany)
HasMany(Function(x) x.DesignersDesigns)
End Sub
End Class
new edit-- the entity property looks like this
Public Overridable Property Name() As String
Get
Return _name
End Get
Protected Set(ByVal value As String)
_name = value
End Set
End Property
am i going the right way..?
I'm not quite sure as the mappings seem ok. I can see one error tough, you have only mapped one of your classes:
.Mappings(Function(x) x.FluentMappings.Add(GetType(DesignMap)))
That should not cause this type of error tough. If you add both your mappings and call the method .ExportTo(#"C:\your\export\path") you will get the actual xml mappings. This way it's easier to see the error. You can do that like this:
.Mappings(Function(x) x.FluentMappings.Add(GetType(DesignMap)).Add(GetType(DesignerMap
).ExportTo(#"C:\your\export\path"))
You can also use the method AddFromAssemblyOf (or some other. There is a few choices) if you don't want to add the mappings one by one.
Try exporting the mappings and see if you can find any error. Or you can post the xml mappings and someone else might find something.
There are several things that can cause this. When using automappings, you will get this if you incorrectly specify the assemblies and namespaces to look in. Other things (more likely in your case) that could cause it, are entity properties that aren't marked as public virtual, having an entity constructor with arguments, but neglecting to make a default constructor, or inheriting your entities from a base class.
I would probably first check to make sure all of your entity properties are "public virtual".
found the problem...the constructor for the map was wrong...it should be like this...
Public Class DesignMap
Inherits ClassMap(Of Design)
Public Sub New()
Table("DesignList")
Id(Function(x) x.DesignId)
Map(Function(x) x.DesignType)
References(Function(x) x.Designer, "DesignerId")
End Sub
End Class
problems of working in both C# and vb.net at the same time i guess..!!
and "Matthew Talbert" was correct...making all the properties Overrideable is important..
thanks guys...:)

Extend System.Web.HttpContext.User

I would like to extend the System.Web.HttpContext.User object (ASP.NET/VB.NET) so that it contains other fields besides just Name. I understand I can create an object that inherits the System.Security.Principal.GenericPrincipal class, but how do I store that in the Current.User object in a usable fashion. ie, I can do something like Current.User.UserID.
So far to achieve this I've created a kludgy workaround by using | delimited strings in the User.Name property and then splitting them, but it's getting kind of ridiculous.
Any suggestions?
Thanks!
EDIT: I have tried the following to no avail:
Imports System.Security.Principal
Public Class CurrentUser : Inherits GenericPrincipal
Private _totalpoints As Integer
Private _sentencecount As Integer
Private _probationuntil As DateTime
Public ReadOnly Property TotalPoints() As Integer
Get
Return _totalpoints
End Get
End Property
Public ReadOnly Property SentenceCount() As Integer
Get
Return _sentencecount
End Get
End Property
Public ReadOnly Property ProbationUntil() As DateTime
Get
Return _probationuntil
End Get
End Property
Public Sub New(ByVal principle As IIdentity, ByVal roles() As String, _
ByVal points As Integer, ByVal sentences As Integer, ByVal probationTil As DateTime)
MyBase.New(principle, roles)
_totalpoints = points
_sentencecount = sentences
_probationuntil = FixDBNull(probationTil)
End Sub
End Class
setting the object in my Global.asax Application_AuthenticateRequest function like so:
HttpContext.Current.User = New CurrentUser(User, userRoles, _
points, sentenceCount, probationUntil)
with a direct cast wherever the object is needed like so:
Dim thisUser As CurrentUser = DirectCast(Current.User, CurrentUser)
i also tried CType and it didn't work... my error is
[InvalidCastException: Unable to cast object of type 'System.Security.Principal.GenericPrincipal' to type 'myProject.CurrentUser'.]
i'm losing my mind here ... :( thanks guys...
anyone?
You can create your own Principal class with the required properties, that inherits from a Generic Principal, and then set the User property of your Current Context to be the a user of that type.
The example below is for ASP.Net MVC but a similar approach could be used with webforms.
You can do this in the PostAuthenticateRequest after a user is authenticated (in the Global.asax)
private void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
SomePrincipal newUser = new SomePrincipal(User.Identity, tmpRoles);
senderRef.Context.User = newUser;
System.Threading.Thread.CurrentPrincipal = newUser;
}
You could then add a property or method in a base class of your page (or controller) for example that to wrap and type the Context.User principal to your Principal type and make sure you call it rather than calling the one on the HttpContext.
There are probably other solutions too!
Would this approach work for you? It looks a little involved but it really doesn't take too long to setup:
Create a 'base' class of your own, and have your pages inherit from that. For example, create a base class called 'BasePage' which inherits from System.Web.UI.Page.
Have your ASP.net pages inherit from your new BasePage class.
In the BasePage class, you can have a public property which contains the extra fields you want to store for your user (eg. BasePage.FirstName, BasePage.LastName). Better still, create a User object containing the extra fields, and expose that via BasePage, eg. "BasePage.Customer". This keeps things tidy if you plan to extend BasePage later.
You can then override the OnInit() of the base class to check for HTTPContext.Current.User.Name property, and fetch the necessary info from your DB to initialise your custom properties.
You can modify the code so that it won't need to hit the database each time the page is refreshed by using ControlState to check whether the custom fields have values before populating them again from the database.
Hope this helps...
Richard.

Resources