Entity Framework Code First : One-To-One association using Annotations - asp.net-mvc

I am having .NET MVC 5 and Identity...
I am trying to get a one to one relationship for my Member class to my MemberInfo class..
So, My classes looks something like this:
IdentityUser is in the Microsoft.AspNet.Identity.EntityFramework namespace with string Id as its ID.
public class GRNUser : IdentityUser {
....
....
}
public class MemberUser : GRNUser {
public virtual Member MemberInfo {get; set; }
}
public class Member {
public int ID {get; set; }
public string MemberUserID {get; set; }
public virtual MemberUser MemberUser { get; set; }
}
In my Context, I have this
modelBuilder.Entity<Member>().HasRequired(m => m.MemberUser)
.WithOptional(u => u.MemberInfo);
So, the MemberUser and Member should be able to navigate to and from each other using the MemberUser's ID property and Member's MemberUserID property.
However, when my Database is created, it has an additional column "MemberUser_Id" instead of using my MemberUserID that I specified. How do I make it use "MemberUserID" that I specified?
I've tried using a few combination so of the ForiegnKey Data Annotation, but keeps on getting this error:
Member_MemberUser_Source: : Multiplicity is not valid in Role 'Member_MemberUser_Source' in relationship 'Member_MemberUser'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

I don't know whether i understood you right or not, but i'l do my best to help.
(I'l assume that you work with code first migration)
If you want to make a one-to-one relation, why not try to make a standalone entity for your info which will have a foreign key for the user entity and that foreign key will be annotated as the primary key of the entity?
Another way is why just not add whatever attributes you like to the Application User entity and work with it?
In any case i might have misunderstood your purpose, so please feel free to explain further since your post is a bit confusing.

Related

Set a Primary Key for an Entity without ingaffect database

I'm working on an ASP.NET MVC project, I use Entity Framework (Database First), I created a data model depend on SQL server database, I created a Table in the database and I updated the data model from the database, and when I try to add a record to the new table I created (this table doesn't have a PK) I got an error, when I search about the error I Understood that in Entity Framework need to have a PK for Entity.
So I ASK if I can set a Primary Key for an Entity without affect database, or any other solution to solve this problem.
You can use partial Class for set Key and without effect Original Model and Database
// orginal class **Entity** `YourEntity.cs`
public class YourEntity
{
public int Id { get; set; }
}
Then create a new Class must name different ordinal class ex YourEntityMeta.cs it is physical name
// must change name ordinal class `YourEntity.cs` but add **partial** keyword
[MetadataType(typeof(Metadata))]
public partial class YourEntity
{
sealed class Metadata
{
[Key]
public int Id { get; set; }
}
}
Entity Framework always needs a primary key column with name id. Add a column (id) in the database table and set "Is Identity: true" for it. Then update the database model of your project.

How to rename Primary key Column in code first approach in ASP.net MVC?

I am using EF code first approach. I need to rename my PK column name.
public class classname
{
[Key]
public int OldId { get; set; }
}
I need to change OldId to NewId. I tried renaming my OldId to NewId, I tried updating my database with Migration but that didn't help.
I tried renaming both in column name and model and again when I tried to update my database I still get error.
How can I rename my primary Key column without losing its data?
Is the question that OldId is not used in your code anymore but is still in your database, or is your problem that it OldId is in your code but has a different column name in your database?
You can use fluent API or data annotations if you want to tell entity framework that the name of property in your DbSet has a different column name in the database:
Fluent API Method
public class MyDbContext : DbContext
{
public DbSet<ClassName> ClassNames {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Tell entity framework that you are now building ClassName:
var classNameConfig = modelBuilder.Entity<ClassName>();
// ClassName has an int primary key in OldId:
classNameConfig.HasKey(className => className.OldId);
// "columnX" in the database corresponds with property OldId
classNameConfig.Property(className => className.OldId)
.HasColumnName("columnX");
}
}
Of course in this specific example this can be concatenated into one statement.
The nice thing about fluent API is that you disconnect your classes from the actual database representation. This hides how the actual database names its columns, column order, min size, max size etc from the user of the DbSets.
Just specify a different DbContext, and you can use the same classes with a different Db.
For instance, if you want to use the same entity framework classes in different databases:
class BaseContext : DbContext
{
public DbSet<MyClass> MyClasses {get; set;}
}
// context to be used with database X:
class DataBaseXContext : BaseContext
{
protected override void OnModelCreating(
DbModelBuilder modelBuilder)
{
// I want to use "columnX" for property A, which is optional:
modelBuilder.Entity<MyClass>
.Property(p => p.A)
.HasColumnName("columnX")
.IsOptional();
}
}
// context to be used with database Y:
class DataBaseXContext : BaseContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// I want to use "columnY" for property A, which is required:
modelBuilder.Entity<MyClass>
.Property(p => p.A)
.HasColumnName("columnY")
.IsRequired();
}
}
Data Annotations Method
If you are absolutely sure you want your classes to be used in only one database, with one pre-defined model, you could use Data Annotations.
However, your question shows that it is not uncommon that the same classes will be used in a different database model. So, although this method is very commonly used, I urge you to reconsider a decision to use Data Annotations.
public class classname
{
[Key]
[Column("ColumnX")]
public int OldId { get; set; }
}
changing the Identity column may lead to instability and you cant change anything with the column unless you kill all the Key constraints (all table relation ship)
t will be tooo complicated i would advice you that if data isnt Important then just delete the database and re run migraions it will recreate the database again
The name of the entity property can be different from the name of the database column.
If you need to change the name of the column on the database you can do it with the DBMS manager (SQL Server Enterprise Manager if you are using SQL Server) or running the proper DDL statement (sp_rename on SQL Server) then set the new column name on the property using the attribute ColumnAttribute
[Column("NewId")]
[Key]
public int OldId { get; set; }
If you need to change the name in the code but not on the database you can do a similar thing
[Column("OldId")]
[Key]
public int NewId { get; set; }
In this case you should do a refactor (rename with F2 if you have standard visual studio Keys or Ctrl+R, R if you are using resharper)
If you need to change both you can do both.

MVC 5 Scaffolding with inheritance uses the wrong entity set

With MVC 5 and EF 6.1 I am using a simple inheritance hierarchy, where class Student inherits from class Person. For both classes I have an entity set (DbSet property) in my database context:
public class DatabaseContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Student> Students { get; set; }
}
Now when I ask the scaffolder to generate a controller for Student, the subclass, it uses the Persons entity set, leading to statements such as
Student student = db.Persons.Find(id);
where the compiler obviously complains that it cannot just convert any Person to a Student.
Is there a way to make sure that the scaffolder uses the correct entity set (Students in this case)?
Note that removing the Persons entity set is not a good solution, because there are other controllers that need that.
Use find and replace to change all occurrences in the Controller class of the parent DBSet to the child DBSet eg change Persons to Students.
As you probably know (as I think you raised it) Microsoft have confirmed this is a known bug http://connect.microsoft.com/VisualStudio/feedbackdetail/view/945937/mvc-5-scaffolding-with-inheritance-uses-the-wrong-entity-set but they won't be fixing it.
Instead of inheritance why not use a relationship making personID the Foreign key ? That why you can db.students.find(personID)
And
db.person.find(personID)
To find all details ?
Extra code but I can't think of another way
You can use the command OfType<>, as shown:
Student student = db.Persons.OfType<Student>().SingleOrDefault(s => s.id == id);
This command works with inheritance. In this case, when Student inherits from Person.

Fluent Nhibernate HasMany to One Table from Several Tables

I have an entity/class/table which is referenced from several other entities, and I use Fluent NHibernate to handle the ORM for me. In a few instances, it's a simple reference where I can store the foreign key ID as a column and handle the reference in that simple way, but in a few other instances I need to reference a list of these items, and it needs done for at least three classes I can think of. You can assume this setup will be copied to handle the other classes' relationships.
Here's how the common entity looks (the one that is owned by several other entities in HasManys):
public class Student {
public virtual int Id {get; set;}
public virtual string Name {get; set;}
}
And, here's what the ShopCourse entity looks like:
public class ShopCourse {
public virtual int Id {get; set;}
public virtual int Name {get; set;}
public virtual IList<Student> Students {get; set;}
}
Imagine that a couple other classes I have, such as specific courses, can "own" several students. In order to maintain that relationship I must create a table in my database that tracks the foreign keys between the two (for each entity that references Student) - no entity needed for this intermediate table, and Fluent won't need to think of it unless I hand it the string name of the table itself:
Table: ShopCourseStudents
int - ShopCourseId
int - StudentId
Lastly, here are my mappings. You can assume that the entities themselves map out fine - things such as the naming scheme for the Id are resolved and working correctly. The issue lies when I attempt to initialize any entity that has a HasMany of Student:
//Inside a FluentlyConfigure().Mappings(m => m.AutoMappings.Add() call:
.Override<ShopCourse>(map => {
map.HasMany(x => x.Students)
.Table("ShopCourseStudents")
.KeyColumns.Add("ShopCourseId")
.KeyColumns.Add("StudentId")
.Cascade.All();
})
The issue is that when I attempt to load a list of ShopCourses I get the Fluent error:
Foreign key (ABC123AF9:Student [ShopCourseId, StudentId]) must have
same number of columns as the referenced primary key (ShopCourses
[Id])
I do not override Fluent's mapping of Student as it's straightforward. For the purpose of this example, Student doesn't need to know which ShopCourses it belongs to, or any of the other courses that may own that particular Student record.
This seems like I'm doing something basic, wrong - what is it, exactly? Much obliged in advance!
So, the issue was with the custom code that I re-use with my projects, apparently the piece written to handle the ManyToMany convention is mostly broken. What I was looking for here was a ManyToMany relationship, not HasMany. The issue I had was that my code was forcing a reference on the child object (in this example, Student) to the parent, which I do not need and only complicates things. Removing that, and my ManyToMany then works:
.Override<ShopCourse>(map => {
map.HasManyToMany(x => x.Students)
.Table("ShopCourseStudents")
.ParentKeyColumn("ShopCourseId")
.ChildKeyColumn("StudentId")
.Cascade.All()

using Guid as PK with EF4 Code First

I have this class and table:
public class Foo
{
public Guid Id {get;set;}
public string Name {get;set;}
}
create table Foo
(
id uniqueidentifier primary KEY DEFAULT (newsequentialid()),
name nvarchar(255)
)
the problem is that when i try to save new foo the first one goes with the 0000-000-00 ... id and the second also, so I get constraint exception
anybody knows a fix ?
Have you set Identity StoreGeneratedPattern?
You can do it in the OnModelCreating method:
modelBuilder.Entity<Foo>().Property(o => o.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
or using the DataAnnotation attributes:
public class Foo {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id {get;set;}
public string Name {get;set;}
}
Just building on Devart's Solution, I had this issue and using the
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
data annotation didn't work. The reason for this was i was using (as suggested in one of the code first tutorials) a SqlServerCompact database which doesn't support the Guid as identity. Just thought I'd post here in case anyone else had this issue. If you change the connection string so it is creating a SqlServer mdf instead of a Compact database it works perfectly.

Resources