I have been going crazy with trying to load multiple partial views in an MVC 5 app I am writing in VB.Net. Don't ask Why VB, the client insisted on it.
The app has a form that pulls from six lookup tables and I need to make a form that the administrator can edit the values of these lookup tables from.
The app has an edmx that the main form is built on and includes these six tables which worked very well for creating the main form, but I cannot find any way to create 6 partial views and load them into a single form.
I have tried How to Return partial view of another controller by controller? to load my partials and I have created separate classes and a View Model based on other posts.
Here is the code from the classes and view model I have tried with no luck.
My Classes.
Public Class CotListIems
Partial Public Class PlanList
Public Property Id As Integer
Public Property Superior As Decimal
Public Property Royal As Decimal
Public Property Maximo As Decimal
Public Property Manual As Boolean
Public Property ManSuperior As Nullable(Of Decimal)
Public Property ManRoyal As Nullable(Of Decimal)
Public Property ManMax As Nullable(Of Decimal)
End Class
Partial Public Class PlanRateList
Public Property Id As Short
Public Property Plan As String
Public Property Rate As Decimal
End Class
End Class
My View Model
Public Class AdminViewModel
Public Property PlanList As IEnumerable(Of PlanList)
Public Property PlanRateList As IEnumerable(Of PlanRateList)
End Class
My Controller
Function Admin(ByVal id As Integer?) As ActionResult
Dim viewModel = New AdminViewModel()
viewModel.PlanList = db.Plans.Include(Function(i) i.Id).Include(Function(c) c.Superior).Include(Function(c) c.Royal).Include(Function(c) c.Maximo).Include(Function(c) c.Manual).Include(Function(c) c.ManSuperior).Include(Function(c) c.ManRoyal).Include(Function(c) c.ManMax)
viewModel.PlanRateList = db.PlanRates.Include(Function(i) i.Id).Include(Function(c) c.Plan).Include(Function(c) c.Rate)
Return View(viewModel)
End Function
The Controller I added here is one that I tried to create, but I have also tried to scaffold one.
When I try to scaffold a new controller based on my view model I get Entity Type 'AdminViewModel' has no key defined. Define a key for this EntityType.
I cannot find any information on how to define a key for this, only for C#, all VB documentation seems to only work for anonymous types and looks to be static hard coded key values.
I'm really stuck here as it seems there are many ways and all I want to do is list the contents of six lookup tables on the same page with Edit links for each section to load them in another view.
Thanks, I know this is probably basic stuff, but it's confusing and very frustrating at the moment.
Related
VS2013, code first EF6, SQL database, VB
I defined the following classes:
Public Class Question
Public Property QuestionID As Integer
Public Property Text As String
Public Property Type As qType
Public Property PossibleAnswers As New List(Of qAnswer)
End Class
Public Class qAnswer
Public Property qAnswerID As Integer
Public Property Text As String
End Class
When I view the qAnswer data table created in the SQL server I see:
In order to do something so simple as display a list of all answers and their parent questions I need to retrieve the value that is obviously in the table, but I don't understand how to code it. Since it's not technically a property of the class I can't call for it directly. How do I retrieve that value?
I'd like to know if the manner of retrieval will work in both the source code, meaning VB, and the view code, meaning Razor.
Because you created a navigation property to qAnswer on Question, Entity Framework created an implicit foreign key to Question on qAnswer to store the relationship. This results in the Question_QuestionID property you see in your database table. However, since this is an implicit property, there's no way to directly access its value in code. You have two options, and you might want to actually do both.
Add a reference property to qAnswer. If you don't actually care about the related question id, explicitly, and just want to be able to get at the question itself, then you can do so through the reference property. Just add something like the following to qAnswer:
Public Property Question As Question
If you want the id, itself, then you need a property to on qAnswer to store it. Something like:
Public Property QuestionID As Integer
By convention, Entity Framework will recognize this as the foreign key property for the relationship and use it accordingly. You'll need to run a migration after adding this property for it to take effect.
Assume we have a class called "MyClass"
Public Class MyClass
End Class
this class has a function called "My function"
Public Class MyClass
Public Function MyFunction()
End Function
End Class
This class has been implemented for some time and its been working fine. Now we need to change the implementation of the function "MyFunction". One option would be to open the source code and change it there. But I'm guessing there has to be a better approach.
Inheritance comes to mind but I don't want to change the derived classes name. I want the name of the class to still remain "MyClass", But I'm guessing the code below will cause an error:
Public Class MyClass
Inherits MyClass
Public Function MyFunction()
End Function
End Class
In other words I'm trying to create a new version of the old class by keeping most of the members the same but just changing a few functions.
To explain the project as a whole, The program is meant for structural design. What it does it designs structural components (i.e columns, beams, slabs, ...). The design procedures are specified by 3rd parties (government regulations). For example:
In the year 2007 government regulations specified that column dimensions are to satisfy the equation F:
H*B < Fy^2/L
In the year 2008 they introduced a new function G and they say column dimensions must satisfy this new function:
H*B^2 < Fy^0.5/E+Alpha^2/L
Where H and B are column dimensions.
What I don't want to do is to open the source code every year and make these changes. I want to somehow override the functions that need to be changed without opening the source.
Any Ideas?
The code is generally not supposed to be changed over time. That is - if you wrote code that is guaranteed to break after 2 weeks by itself, you probably should reconsider your design.
As you rules/regulations come out, you usually update your input data (in a form of XML, or a relational database for large amounts of data), and your program would automatically pick those up.
The only case you would update your program under this scenario is when new type of regulations come out. But even in this case the changes are usually minimal.
A good anti-pattern example for this - you have 500 forms, each of them has 500 lines of code, so that's 250000 lines of code in your UI layer. New regulations come out that requires changing 50% of the code in each form. Your impact is 125000, which at 40 lines of code per day would take 8.5 developer-years.
A solution to this would be having a change of 100 lines spread across all forms, adding 1 line in each, or leaving everything as is. Also there will be a data load/conversion procedure from a government/other file, which populates your database in the proper format, updating the values or adding new ones. There may be 10 lines of change in that program, but that's about it, 3 days worth of work, if you believe in 40 LoC per day. Otherwise it still falls under 2 weeks of developer's time.
Depending on how you implement it, the benefit of this approach could be that you support old standards as well, so older input can be matched and production reports can be generated. It is a good practice to be able to back-date your reports, cause sometimes there are issues in report code left unnoticed for months before being discovered.
EDIT: A more structured approach to what I suggested in the comments would be storing expression trees in the DB. Most simple form of it is just a linear workflow, using postfix notation (single table). For example A, B, + C - is equivalent to A + B - C. You can then have a user interface for some configuration tool, which only allows user to input values and functions that are applicable. This is assuming applicable values are also stored in DB as parameters (one structural component can have 0...N of them).
Inheritance can do what you want but you need to create a new ancestor, not descendant.
Change the name of the original class to something that denotes that it is a base class. Also, add the MustInherit modifier to the class and Overridable to any of the methods or properties that you may need to override.
One thing to watch for is Private members in this base class. Any members that need to be accessible from the descendant class cannot be Private and must be changed to Protected.
The original class looks like this.
Public MustInherit Class MyBaseClass
Public Overridable Function MyFunction() As String
' code...
End Function
Public Overridable Function AnotherFunction() As String
' code...
End Function
End Class
Now create a new class with the original class's name which inherits from the base class. Override just the members that need to be different.
Public Class MyClass
Inherits MyBaseClass
Public Overrides Function MyFunction() As String
' new code...
End Function
End Class
That will get you started. The Template Pattern will allow you to do more fine grained code changes where only parts of a method need to be changed.
The formula is a bit complicated and you'll still need to change some code unless you store these in a database somehow.
An option would be to use inheritance with a factory method.
Public Class BaseClass
Public MustOverride Function MyFunction()
Public Function GetInstance(ByVal year As Integer) As BaseClass
If year = 2007 Then Return New Class2007()
If Year = 2008 Then Return New Class2008()
End Function
End Class
Public Class Class2007
Inherits BaseClass
Public Overrides Function MyFunction()
' H*B < Fy^2/L
End Function
End Class
Public Class Class2008
Inherits BaseClass
Public Overrides Function MyFunction()
' H*B^2 < Fy^0.5/E+Alpha^2/L
End Function
End Class
then, everywhere in your code you use BaseClass never knowing that Class2007 and Class2008 exists
Dim o As BaseClass
o = BaseClass.GetInstance(2007)
o.MyFunction()
Depending on the need, this can also be done with interface.
If you need to store the formulas in the database as string, you'll need to get a parser and this can also be found using 3rd party library. https://stackoverflow.com/questions/1387430/recommended-math-library-for-c-net
-Edit- This is for a finance API I am designing. I am in the process of creating some empty classes, getting a feel for the general structure. My primary concern is designing a pleasant user experience without requiring a manual to explain how to use it. -End Edit-
I have been scratching my head trying to think of the best way to go about designing a specific class. I will create a general example to illustrate.
Namespace SomeNamespace
Public Class Results
Public a1 as Integer
Public a2 as Integer
...
Public b1 as Integer
...
Public z1 as Integer
End Class
End Namespace
The example above is generic, but the point is there are many values within the class. The letter in the variable name represents a similar group of results. The "a" results are similar, "b" similar, etc. I had thought to make a class for each type of result value (since they are a type of result, but separate concepts from each other) within the Results class such as...
Public Class Results
Class a
Public a1 as Integer
End Class
Class b ... End Class
End Class
The problem with this is that it is not explicit that when a person uses the class
Dim ResultObject as new SomeNamespace.Results.a()
the Results object would have to be instantiated first, because any of the sub-classes a,b, etc would rely on the Results object. But the user would see the objects a,b, etc and perhaps not know that they must create the parent object first.
I thought about making the classes separate and each constructor would create a Result object, but that seems backwards logically. Any Advice? Sorry if it was confusing.
Why not make an Abstract class Result and create an inheritance structure ResultTypeA, ResultTypeB etc.? With no details on the problem it is really hard to give a meaningfull answer.
Why not use a single 2-dimensional integer array, where the first index is the result class (i.e. letter 'a' or 'b' etc), and the second index is the result number (i.e. a1 or z2 etc)?
Two quick recommendations.
1) In classes, don't expose your fields. Only expose methods and properties. If you're using auto implemented properties this is done by just adding the Property keyword in your declaration. Otherwise, declare your field as private and the property that exposes it as public:
Public Class Foo
Private _V1 As Integer ' Backing field
Public Property V2 As Integer ' Auto Property
Public Property V1 As Integer ' With backing field
Get
Return _V1
End Get
Set (Value as Integer)
_V1 = value
End Set
End Property
End Class
2) Don't nest your class declarations. Instead of
Public Class Results
Class a
Public a1 as Integer
End Class
Class b ... End Class
End Class
Do the following:
Public Class Results
Public Property A1 As A
Public Property B1 As B
End Class
Public Class A
Public Property A1 As Integer
End Class
Public Class B
Public Property B1 As Integer
End Class
For naming conventions, you should name your properties as nouns and methods as verbs. I regarding your ordering question, I recommend starting with the category (noun) and then adding adjectives after it in increasingly specific terms:
Property NameFirst As String
Property NameLast As String
Property ContactEmail As String
Property ContactPhoneHome As String
Property ContactPhoneWork As String
I am using Entity Framework 4.1 code first+MVC3 and the inheritence stratagy that I use is TPC
I have the following classes
Public Class ObjectBase
<Key()>
Public Property Id As Integer
Public Property Description As String
End Class
Public Class Computer
Inherits ObjectBase
Public Property Computername As String
End Class
Public Class Book
Inherits ObjectBase
Public Property BookName As String
End Class
Public Class User
<Key()>
Public Property Id As Integer
Public Property Name As String
End Class
Public Class BorrowObject
<Key()>
Public Property Id As Integer
Public Property User As User
Public Property BorrowedObject as ObjectBase
End Class
Public Class BorrowComputerVM
<Key()>
Public Property Id As Integer
Public Property User As User
Public Property Computer as Computer
End Class
My questions are:
How do I do a query (using LINQ,
Entity SQL or other commonly used
way) to get all BorrowObjects where
BorrowedObject is of type Computer?
How do I map the result of the query
to the ViewModel called
"BorrowComputerVM" (used for
creating views only used for
borrowing a Computer).
Question 1 (and question 2) should be very simple, but I have allready spent hours on Google to find an answer with no result at all. The only thing I have found is that you can get all computers in ObjectBase by writing context.ObjectBase.OfType(Of Computer), and that does not help since you cannot write context.BorrowObjects.ObjectBase.OfType(Of Computer)
Please provide code samples in VB.NET (if you can), but more importantly: Please ensure that the codesamples you supply work without hours of modification!
I write it in C#:
How do I do a query (using LINQ, Entity SQL or other commonly used way)
to get all BorrowObjects where
BorrowedObject is of type
Computer?
var list = context.BorrowObjects.Include(b => b.BorrowedObject)
.Where(b => b.BorrowedObject is Computer)
.ToList();
You can omit the Include if you don't want to eager load the Computer.
How do I map the result of the query to the ViewModel called
"BorrowComputerVM" (used for creating
views only used for borrowing a
Computer).
var list = context.BorrowObjects
.Where(b => b.BorrowedObject is Computer)
.Select(b => new BorrowComputerVM
{
Id = b.Id,
User = b.User,
Computer = b.BorrowedObject as Computer
})
.ToList();
Includes are not necessary if you project into a new type: User and Computer will be loaded in the BorrowComputerVM also without explicit Include.
The is and as operators work indeed in LINQ to Entities.
This article describes a lot of configuration that's required for code-first TPC inheritance, as well as some special techniques you need to use. Has all of that already been done? If you've completed all the coding jujitsu described in the article, it seems like the query syntax or object structure shouldn't pose much of an obstacle to you.
I'm just learning to work with partial classes in VB.NET and VS2008. Specifically, I'm trying to extend a LINQ to SQL class that was automatically created by SqlMetal.
The automatically generated class looks like this:
Partial Public Class DataContext
Inherits System.Data.Linq.DataContext
...
<Table(Name:="dbo.Concessions")> _
Partial Public Class Concession
...
<Column(Storage:="_Country", DbType:="Char(2)")> _
Public Property Country() As String
...
End Property
...
End Class
In a separate file, here's what I'm trying to do:
Partial Public Class DataContext
Partial Public Class Concession
Public Function Foo() as String
Return DoSomeProcessing(Me.Country)
End Function
End Class
End Class
... but I get blue jaggies under 'Me.Country' and the message 'Country' is not a member of 'DataContext.Concession'. Both halves of the partial class are in the same namespace.
So how do I access the properties of the automatically-generated half of the partial class, from my half of the partial class?
Unless VB.NET generates different stuff in its LINQ to SQL files from C# the classes of the DB tables aren't within the DataContext class, just beside it.
So you have the class MyNamespace.DataContext.Concession when the other half of the partial class is realy MyNamespace.Concession
(This related to VB.NET - might be differences with C# projects)
I put my entities in their own namespace by configuring the Linq-to-SQL model property.
e.g. MyCo.MyProj.Business.Entities
I then add non-Linq business entities in there too, so they are all in the same namespace.
However, when trying to do the above partial class additions, I found that the partial class (i.e. the one you generate, not the auto-generated LINQ class) MUST be in the same project as the Linq-to-SQL model. Otherwise in the Class View and Object Viewer you see two separate classes - seemingly in the same namespace, but not really. Not sure if this is a bug or I am doing something wrong.
But, anyway, putting the partial class file in the same project as your model works.