Entity framework mapping issues - vb.net

I am entirely new to .Net having been working in it for a week at most so please go easy and be detailed as possible :)
I have the following PONO:
Public Class WorkOrderEntity
Private intTrackingNumber As Integer
Private intDateReceived As Integer
Private strManufacturer As String
Public Property TrackingNumber() As Integer
Get
Return intTrackingNumber
End Get
Set(value As Integer)
intTrackingNumber = value
End Set
End Property
Public Property DateReceived() As String
Get
' TODO: Convert timestamp to formatted date
Return intDateReceived
End Get
Set(value As String)
' TODO: Convert formatted date to timestamp
intDateReceived = value
End Set
End Property
End Class
The issue I am faced with is how to store date/time as a timestamp (integer) but provide public properties which format/convert accordingly.
I suppose I could provide a an additional getter()/setter() but ideally I wonder if EF has a way of circumventing this "convention"?
Additionally - I am also curious as to whether it's possible to map properties to columns which are not labelled correctly?
Basically if I were working in a existing database (EF automatically builds my PONO with properties named after table fields) I wish to name the fields something more meaningful; some fields for example might be awkward abbreviations but in the object model I want something more English friendly?
I seem to recall being able to do this with Hibernate in Java (actually it's PHP port) but never the less does EF support such a feature?
Any ideas?

A timestamp SQL Server at least is now a RowVersion. In either case it is not a datetime, but rather a byte array for the version which is auto updated when ever the row changes. You don't convert it to a date.
Regarding mapping an element via configuration rather than convention, you can use the attributes or fluent syntax to specify the mapping. See http://msdn.microsoft.com/en-US/data/jj200620 for info on how to use these features.

Related

Type 'Collection' is not defined vb BC30002

I am attempting to migrate a legacy vb.net application to .net standard and turn it into a nuget package. A good amount of it has been straight forward. I am currently hung up on this error caused by functions like this.
Public Property ErrorMessages As Collection
Get
ErrorMessages = _errorMessages
End Get
Set(value As Collection)
_errorMessages = value
End Set
End Property
If i import System.Collections.ObjectModelCollection(Of T) it is asking me for a type and i am unsure how to proceed. It turns my code into
Collection(Of,) and expects a second argument. Has anyone faced this before? Do i use a different import statement or how is this dealt with in vb now?
You should almost certainly replace Collection with Dictionary(Of TKey, TValue), using the dictionary type from the System.Collections.Generic namespace.
Once again, this requires you to fill in the genetic type arguments TKey and TValue with the actual types. You need to figure out from context which type fits the collection. The value of TKey is probably String since that’s the only key type VB6’ collections properly support. And given the name (ErrorMessages), TValue is probably String as well.

Enum with option to show up second describtion

I have some enum inside my code (below) and i am using this enum to show up the names like e.g that: Datasource.Some_server1.ToString(). I am using it either inside code engine to do some calculation if specific server enum is and also to show the name on the webpage. The problem now is my manager asked me to show up diffrent names. So for instance not Some_server1 but for instance: HHGT Server 56. The problem is my code is using those enum names to do some tasks and i cannot just change it within this enum. Do you know some way i can tell inside my project ok now i want see describtion name for this enum so not Some_server1 but now if Datasource.Some_server1.ToString() then show HHGT Server 56. Is there such possibility without not changing my enum in the way rest of code is still using it? Hope you got what i mean.
Public Enum Datasource
Some_server1
Some_server2
Some_server3
Some_server4
End Enum
You can add more context to your Enum by assigning a Description Attribute to each member.
Public Enum DataSource
<Description("HHGT Server 56")> Some_server1
'etcetera
End Enum
Then you can use this function (taken from a really useful extension) to get the Description string:
Public Shared Function GetEnumDescription(ByVal value As [Enum]) As String
Dim fi As Reflection.FieldInfo = value.[GetType]().GetField(value.ToString())
Dim attributes As DescriptionAttribute() = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
Return If((attributes.Length > 0), attributes(0).Description, value.ToString())
End Function

VB.NET: Writing a function that take specific-type, multiple key-value parameters

I'm trying to write a function in a basic MVC (experimental project) that should be called with the following (or as close to):
datastore = myTable.FetchData({{column1, constraint1},
{column2, constraint2}, ...
{colN, conN}})
Function purpose - It queries a table with the constraints passed to it. For example,
FetchData({{Me.Fields("Price"), "<100"}, {Me.Fields("Type"), "=Component"}})
will ultimately produce the query
SELECT * FROM table a WHERE Price < 100 AND Type = "Component"
(the query production is more involved than that, involving relationships defined and so forth, but that's outside the scope of this question)
How should I write the function definition to take these parameters?
`Public Function FetchData( ??? ) As foobar
Essentially, it will be something similar to a Dictionary, since it's a list of pairs of values. However, it needs to be non-unique (it could be called to produce col1 > 1 AND col1 < 5 for eg). A two-dimensional arraylist has been considered also, but each half of the pair needs to be a specific type - the 'key' needs to be of my ColumnDefinition object type or string, the 'value' should always be a string.
What would be the best way to handle this?
Bonus question: merging the operator in with the constraint ("=component") seems ugly. Any idea about how to write the function def with the operator separate? I tried an enum but that just made it too verbose - I want this to be a fairly easy to use library.
If you are on .NET 4.0 or higher, suggest trying out the Tuple class to represent your queries. Your code may look like below.
Public Function FetchData(ByVal params As List(Of Tuple(Of ColumnDefinition, Char, String))) As foobar
Tuples are only recommended for API's under your control, where the context is obvious. If this is a public or shared API, suggest creating a named class with appropriate properties (as in Nico Schertler's comment). Then, the code may look like.
Public Function FetchData(ByVal params As List(Of MyContainerClass)) As foobar
Hope this helps.
Or according to the shape of the function call you are describing, if you are definitely using strings, and it is always {"Col", "Constraint"} then you could do this
Public Function FetchData(ByVal MultiDimensionArray(,) As String)
'this is then how you could pull the pairs of cols and constraints back out
'where n is the col constraint pair count up to (n) number
For n As Integer = 0 To MultiDimensionArray.Length - 1
Dim Col As String = MultiDimensionArray(0, n)
Dim Constraint As String = = MultiDimensionArray(1, n)
Next
End Function

How can I create an "enum" type property value dynamically

I need to create a property in a class that will give the programmer a list of values to choose from. I have done this in the past using the enums type.
Public Enum FileType
Sales
SalesOldType
End Enum
Public Property ServiceID() As enFileType
Get
Return m_enFileType
End Get
Set(ByVal value As enenFileType)
m_enFileType = value
End Set
End Property
The problem is I would like to populate the list of values on init of the class based on SQL table values. From what I have read it is not possible to create the enums on the fly since they are basically constants.
Is there a way I can accomplish my goal possibly using list or dictionary types?
OR any other method that may work.
I don't know if this will answer your question, but its just my opinion on the matter. I like enums, mostly because they are convenient for me, the programmer. This is just because when I am writing code, using and enum over a constant value gives me not only auto-complete when typing, but also the the compile time error checking that makes sure I can only give valid enum values. However, enums just don't work for run-time defined values, since, like you say, there are compile time defined constants.
Typically, when I use flexible values that are load from an SQL Table like in your example, I'll just use string values. So I would just store Sales and SalesOldType in the table and use them for the value of FileType. I usually use strings and not integers, just because strings are human readable if I'm looking at data tables while debugging something.
Now, you can do a bit of a hybrid, allowing the values to be stored and come from the table, but defining commonly used values as constants in code, sorta like this:
Public Class FileTypeConstants
public const Sales = "Sales"
public const SalesOldType = "SalesOldType"
End Class
That way you can make sure when coding with common values, a small string typo in one spot doesn't cause a bug in your program.
Also, as a side note, I write code for and application that is deployed internally to our company via click-once deployment, so for seldom added values, I will still use an enum because its extremely easy to add a value and push out an update. So the question of using and enum versus database values can be one of how easy it is to get updates to your users. If you seldom update, database values are probably best, if you update often and the updates are not done by users, then enums can still work just as well.
Hope some of that helps you!
If the values aren't going to change after the code is compiled, then it sounds like the best option is to simply auto-generate the code. For instance, you could write a simple application that does something like this:
Public Shared Sub Main()
Dim builder As New StringBuilder()
builder.AppendLine("' Auto-generated code. Don't touch!! Any changes will be automatically overwritten.")
builder.AppendLine("Public Enum FileType")
For Each pair As KeyValuePair(Of String, Integer) In GetFileTypesFromDb()
builder.AppendLine(String.Format(" {0} = {1}", pair.Key, pair.Value))
End For
builder.AppendLine("End Enum")
File.WriteAllText("FileTypes.vb", builder.ToString())
End Sub
Public Function GetFileTypesFromDb() As Dictionary(Of String, Integer)
'...
End Function
Then, you could add that application as a pre-build step in your project so that it automatically runs each time you compile your main application.

Type casting in VB .NET

I am adding a feature to an existing VB .Net application that involves retrieving data from a .Net web service. The web service returns an array of Locations. A Location is pretty simple, it has 3 properties – an integer and two strings.
So that the rest of my application does not have to be dependent on this web service, I would like to create my own Location type within my application. My thought is I could call a method that returns a generic list of my Location type which internally calls the web service and populates the list I return. That way, if the data source for Locations changes in the future to something other than the web service, I only have to fix the method instead of fixing all the callers.
So I created my own Location that has identical properties as the service Location. But I don’t seem to be able to cast the array of service locations into a generic list of my locations. I also tried casting a single service Location into one of my Locations and that didn’t work either.
So is casting an option or do I have to loop through each service Location and assign each property to a new one of my Locations? Or is there a completely different way to go about this?
By default you will not be able to cast one Location to another. They are completely unrelated types and thus cannot be the subject of casting. You can make it possible to cast though by defining a custom operator for the application version of CType.
' Location for application
Public Class Location
...
Public Shared Operator Widening CType(p1 as Namespace.Of.WebService.Location) As Location
Dim loc = ConvertWebServiceLocationToApplicationLocation
return loc
End Operator
End Class
This allows you to now do a CType operation between a WebService Location the Application Location.
Casting the array though, simply won't be possible. There is no way to define a conversion operator for arrays so they can't use the above trick. But you can write a quick and dirty function for this purpose
Public Shared Function ConvertArray(ByVal arr As Namespace.Of.WebServiec.Location()) As Location()
Dim newArray(arr.Length) As Location
For i as Integer = 0 To arr.Length - 1
newArray(i) = CType(arr(i), Location)
Next
return newArray
End Function
Casting will not work because these are not the same type. Even if two types look exactly the same, you cannot cast from one to the other, unless you define a CType operator which describes how to transform an object from one type into an object from another type.
Even then, you cannot cast a List(of Type1) into a List(Of Type2) directly.
You will have to loop through and create a new object of your class.