I'm trying to simply access information in a existing database using vb.net MVC. The issue is, when i run the code, it creates a table in the database, with a name similar to the table I'm attempting to access with an 's' appended on the end.
e.g:
Existing table: VXPartsData.
Table created after running application: VXPartsDatas
I've managed to do this in c sharp quite easily, but don't understand where I'm going wrong using VB. If someone could please point me in the right direction, thanks
Imports System.Data.Linq
Imports System.Data.Linq.Mapping
Imports System.ComponentModel.DataAnnotations
Imports System.Data.Entity
Namespace Models
<Table(Name:="dbo.VXPartsData")>
Public Class VXPartsData
<Key()>
Public Property PartNo As String
Public Property CustPart As String
Public Property ShortDesc As String
Public Property Part As String
Public Property Price As Decimal
Public Property DiscCode As String
Public Property Kit As Boolean
Public Property VXCODE As String
End Class
Public Class ProductContext
Inherits DbContext
Public Property VXPartsDatas As DbSet(Of VXPartsData)
End Class
End Namespace
Controller:
Imports System.Data.Entity
Imports Videx_PB2.Models
Public Class HomeController
Inherits System.Web.Mvc.Controller
Private db As New ProductContext
Function Index() As ActionResult
Return View(db.VXPartsDatas.ToList())
End Function
End Class
Connection String:
<connectionStrings>
<add name="ProductContext" connectionString="server=(localdb)\MSSQLLocalDB; database=VidexPB; integrated security=SSPI" providerName="System.Data.sqlClient" />
</connectionStrings>
In your ProductContext class, add the following code:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
...
base.OnModelCreating(modelBuilder);
}
EF will not pluralize table names
Related
I'm trying to migrate an objectcontext/edmx system to dbcontext (EF6) with fluent mapping. I have a few instances like the following. Principal table has a relationship to a dependent table where a non-PK column in the dependent table holds the value of a PK column in the principal. On its own this would be a one to many relationship, but there is a unique index on the dependent table FK columns. Using EDMX mapping, this works fine as long as you define the relationship using mapping rather then referential constraints. Below is an executable example - you don't need the database because it doesn't get that far, currently:
Imports System.Data.Entity
Imports System.Data.Entity.ModelConfiguration
Module Module1
Sub Main()
Using session As New SaturnEntities
Dim res = session.BookingLegSet.Select(Function(x) New With {x.Prefix, x.ID, x.AddressDetails.Address}).ToList
End Using
End Sub
End Module
Partial Public Class BookingLeg
Public Property Prefix As String
Public Property ID As Integer
Public Property LegIndex As Integer
Public Overridable Property AddressDetails As BookingLegAddress
End Class
Partial Public Class BookingLegAddress
Public Property Prefix As String
Public Property ID As Integer
Public Property Address As String
Public Overridable Property BookingLeg As BookingLeg
Property JobLegPrefix As String
Property JobLegID As Integer?
End Class
Public Class BookingLegConfig
Inherits EntityTypeConfiguration(Of BookingLeg)
Public Sub New()
ToTable("JobLegs", "dbo")
HasKey(Function(x) New With {x.Prefix, x.ID})
HasOptional(Function(x) x.AddressDetails).WithRequired(Function(x) x.BookingLeg).Map(Function(x) x.MapKey("Prefix", "ID"))
End Sub
End Class
Public Class BookingLegAddressConfig
Inherits EntityTypeConfiguration(Of BookingLegAddress)
Public Sub New()
ToTable("JobAddresses", "dbo")
HasKey(Function(x) New With {x.Prefix, x.ID})
HasRequired(Function(x) x.BookingLeg).WithOptional(Function(x) x.AddressDetails).Map(Function(x) x.MapKey("JobLegPrefix", "JobLegID"))
End Sub
End Class
Partial Public Class SaturnEntities
Inherits DbContext
Public Sub New()
MyBase.New("data source=dbSaturn;initial catalog=Saturn;integrated security=True;MultipleActiveResultSets=True;")
End Sub
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
modelBuilder.Configurations.Add(New BookingLegConfig)
modelBuilder.Configurations.Add(New BookingLegAddressConfig)
End Sub
Public Overridable Property BookingLegAddressSet() As DbSet(Of BookingLegAddress)
Public Overridable Property BookingLegSet() As DbSet(Of BookingLeg)
End Class
BookingLeg is the principal entity and BookingLegAddress is the dependant. JobLegPrefix and JobLegID in the dependent will be either null or will hold the Prefix and ID values from a BookingLeg record. When you run this you get an error that AddressDetails has been configured with conflicting mapping information. I've tried numerous different ways to map this, but haven't got anywhere - can anyone tell me what I need to do?
Remove the
HasOptional(Function(x) x.AddressDetails).WithRequired(Function(x) x.BookingLeg).Map(Function(x) x.MapKey("Prefix", "ID"))
line from BookingLegConfig class. Every single relationships must be configured only once in a single place (part of the configuration of any of the two involved entities, but not in both). In this particular case you should keep the second configuration inside BookingLegAddressConfig class
HasRequired(Function(x) x.BookingLeg).WithOptional(Function(x) x.AddressDetails).Map(Function(x) x.MapKey("JobLegPrefix", "JobLegID"))
because it specifies the correct FK column names.
Also EF6 does not support explicit FK columns for this type of relationship - no HasForeignKey fluent API, and MapKey is for specifying shadow property (and column) names. So additionally remove the JobLegPrefix and JobLegID properties from the BookingLegAddress class:
Partial Public Class BookingLegAddress
Public Property Prefix As String
Public Property ID As Integer
Public Property Address As String
Public Overridable Property BookingLeg As BookingLeg
End Class
I'm using ASP.NET MVC5 with Identity 2 framework, Database first
I'm trying to custom AspNetRoles, by adding a column called MyCustomColumn
However, my app crashes because :
Invalid Column Name Discriminator
There is a lot of resources on SO and elsewhere on the web, but most of them are with CodeFirst approach and I can't use them in my app.
How to deal with it ?
Actually, none of this is necessary. Most likely you failed to update your context to inherit from IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>, rather than the default of IdentityDbContext<TUser>. Since you did not pass your custom role entity as the TRole type parameter, the context instead uses IdentityRole as the class type. It then creates a table for IdentityRole, sees that your custom role inherits from IdentityRole, and therefore adds the Discriminator column so that it can tell the different between an instance of IdentityRole and your custom role, in the database (single table inheritance is the default strategy EF employs).
This will technically work, but your custom role will never actually be utilized. Use the right generic abstract context class, and you'll be fine.
For what it's worth, you should do away with the EDMX stuff, as well. It's deprecated, buggy, and unnecessary. Despite the name, "Code First" can be used with an existing database or to create a new one.
DON'T
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
DO
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
Ok, as I spend some hours to find a solution, I post it here, if it could help someone else.
First, in AspNetRoles, create your custom column AND a column called Discriminator (which is a nvarchar(max) ). Update your .edmx
Then, we have to create a class which inherits from IdentityRole. We will use this class to access our custom column we just created :
In Models folder
public ApplicationRole()
: base() { }
public ApplicationRole(string name, long myCustomValue)
: base(name)
{
MyCustomValue = myCustomValue;
}
public virtual long MyCustomValue { get; set; }
Then, let's create a class which inherits from RoleManager<ApplicationRole>.
I placed it in IdentityConfig.cs, but maybe it's a best practice to place it elsewhere...
For information, I get inspired by this blog, Re-Implementing RoleStore and ApplicationRoleManager paragraph
public class ApplicationRoleManager : RoleManager<ApplicationRole>
{
public ApplicationRoleManager(
IRoleStore<ApplicationRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(
IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(
new RoleStore<ApplicationRole>(context.Get<ApplicationDbContext>()));
}
}
ApplicationRoleManager has a constructor which calls our previously created ApplicationRole class.
Now we have to register our ApplicationRoleManager at startup, so we have to add this line after the others CreatePerOwinContext
In App_Start\Startup.auth.cs, ConfigureAuth(IAppBuilder app) method
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
So now we can use our ApplicationRoleManager, correctly instanciated :
var rm = new ApplicationRoleManager(new RoleStore<ApplicationRole>(new ApplicationDbContext()));
And then use it as we want
var roleName = rm.FindByName("Admin");
string myCustomData = roleName.CustomData.ToString();
I have seen a few questions like this, but none seem to answer my question - the most common response seems to be 'Lazy Loading - The database/tables will be created when you try to access them' in this case I am:
Dim students As List(Of Student) = db.Students.ToList
The above is throwing an error, because students table is empty/null.
Here is my (very simple) SchoolContext:
Imports System.Data.Entity
Public Class SchoolContext
Inherits DbContext
Public Students As DbSet(Of Student)
End Class
Here is my SchoolInitialiser class:
Imports System.Data.Entity
Public Class SchoolInitializer
Inherits DropCreateDatabaseAlways(Of SchoolContext)
Protected Overrides Sub Seed(context As SchoolContext)
Dim students As List(Of Student) = New List(Of Student) From {
New Student("Jessica", "Jones"),
New Student("Chuck", "Norris"),
New Student("Rambo", "John")
}
For Each student In students
context.Students.Add(student)
Next
context.SaveChanges()
End Sub
End Class
And my connection string in web.config:
<add name="SchoolContext" connectionString="Data Source= (LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\school.mdf;Initial Catalog=aspnet-WebApplication1-20160205092922;Integrated Security=True" providerName="System.Data.SqlClient" />
And finally my global.asax where I am calling the SetInitialize function
Imports System.Data.Entity
Imports System.Web.Optimization
Public Class MvcApplication
Inherits System.Web.HttpApplication
Protected Sub Application_Start()
Database.SetInitializer(New SchoolInitializer)
AreaRegistration.RegisterAllAreas()
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
RouteConfig.RegisterRoutes(RouteTable.Routes)
BundleConfig.RegisterBundles(BundleTable.Bundles)
End Sub
End Class
No database seems to be created within my AppData folder and as far as I can tell, everything is set up okay? Any suggestions?
I am following the following tutorial: https://www.youtube.com/watch?v=VAtVv1Q7ufM
Thanks!
So I figured this one out, in case anybody comes across a similar problem. I was using VB, so I imagine some things got lost in translation from c#.
There were actually a few issues for this. The first one was that the StudentContext class needed properties for the tables, not global variables:
'NOT Public Students As DbSet(Of Student)
Public Property Students() As DbSet(Of Student)
After this, the errors were easier to figure out. The second error was due to not having a key on my Student model, so I added this:
<Key()>
Public Property _StudentID As Integer
To both the property and the global variable. Next, it was not connecting to the database for some reason, so I had to download and install localDB.
Finally, it was complaining that I didn't have a parameterless constructor. So I had to add in an empty constructor in my student model.
FINALLY - everything is working (yay)
I am complete beginner with ASP.net and VB.net, I created two classes one for Teams and another for Fixtures which will take in 2 teams.
Imports System.Data.Entity
Public Class Team
Public Property ID() As Integer
Public Property Name() As String
Public Property Points() As Integer
End Class
Public Class TeamDBContext
Inherits DbContext
Public Property Teams() As DbSet(Of Team)
End Class
Imports System.Data.Entity
Public Class Fixture
Public Property ID() As Integer
Public Property Week() As Integer
Public Property HomeTeam() As Team
Public Property AwayTeam() As Team
End Class
Public Class FixtureDBContext
Inherits DbContext
Public Property Fixtures() As DbSet(Of Fixture)
End Class
I created a FixturesController with the read/write actions and views. However when I go to create a Fixture in my application I only see a field for Week and not field for HomeTeam or AwayTeam.
Well you need to add them manually. Brad Wilson wrote a nice article explaining in details how you could make the templated helpers to recursively descend in your nested models.
Also as a side remark you probably don't need 2 db contexts, one should be enough and it could contain both your Teams and Fixtures:
Public Class FixtureDBContext
Inherits DbContext
Public Property Teams() As DbSet(Of Team)
Public Property Fixtures() As DbSet(Of Fixture)
End Class
I'm new to ASP.NET MVC, altough could call myself experinced programmer in web forms field.
I'm learning MVC now. Trying to add controller with Entity framework abolities.
Here is below code of model class:
Imports System.Data.Entity
Public Class Users
Public Property ID() As Integer
Public Property Login() As String
Public Property Password() As String
Public Property Avatar() As Image
Public Property Country() As Integer
Public Property City() As Integer
Public Property Phone() As String
Public Property Email() As String
Public Property Registered() As Date
End Class
Public Class StopSaleDBContext
Inherits DbContext
Public Property Users() As DbSet(Of Users)
End Class
When I'm adding controller I got error Unable retrieve metadata from ProjectName.Users Object reference not set to an instance of object.
Compile your project and try again.