Mapping View To MVC Code first - asp.net-mvc

I have view in SQL called ViewTest.
In code I have this model
[Table("dbo.ViewTest")]
public class ViewTest
{
public int Id { get; set; }
public int EmployeeID { get; set; }
public string PreferredName { get; set; }
public string EmailPrimaryWork { get; set; }
public string GeoCoverage { get; set; }
public string Role { get; set; }
public bool? LeftEmpFlag { get; set; }
}
In configuration file:
public virtual IDbSet<ViewTest> ViewTests { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ViewConfiguration());
}
public class ViewConfiguration : EntityTypeConfiguration<ViewTest>
{
public ViewConfiguration()
{
this.HasKey(t => t.Id);
this.ToTable("ViewTest");
}
}
I want to have connection like this one ViewTests.Where(....) ,but when I tried to do like this way I have error There is already an object named 'ViewTest' in the database..This means entity framework try to create new Table and I don`t want this.I want to access this view only!

Well, it is code first so you should probably create your view in code. If that is not possible, then you need to tell EF not to create the table by commenting that line out of the Up() method on the migration. Once you update-database EF will have it in the metadata and you should be good to go.

Related

Get data from Sql tables using Entity Framework in MVC

I use VS 2015 and Entity Framework 6.2.0.
I have two tables tblUsers and tblFields in sqlServer.
I create two models related to my tables:
[Table("tblUsers")]
public class Users
{
[Key]
public string UserName { get; set; }
public string UserPassword { get; set; }
public DateTime RegisterDateTime { get; set; }
public string FieldId { get; set; }
public float Score { get; set; }
}
[Table("tblFields")]
public class Fields
{
[Key]
public string FieldID { get; set; }
public string FieldTitle { get; set; }
}
So, in my DataAccessLayer, I have:
public class Dal : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Users>().ToTable("tblUsers");
modelBuilder.Entity<Fields>().ToTable("tblFields");
base.OnModelCreating(modelBuilder);
}
public DbSet<Users> UsersSet { get; set; }
public DbSet<Fields> FieldsSet { get; set; }
}
When I use the following code in BusinessLayer to get Users Data:
public List<Users> GetAllUsers()
{
Dal dal = new Dal();
return dal.UsersSet.ToList();
}
No users are return!
Where is the problem?
I create a database and it's tables. Then I created my project that used from database. The problem is here!
Solution: I deleted all tables from database and then I run my application. Application created all tables again and problem is solved.

Defining multiple Foreign Key for the Same table in Entity Framework Code First

I have two entities in my MVC application and I populated the database with Entity Framework 6 Code First approach. There are two city id in the Student entity; one of them for BirthCity, the other for WorkingCity. When I define the foreign keys as above an extra column is created named City_ID in the Student table after migration. Id there a mistake or how to define these FKs? Thanks in advance.
Student:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int BirthCityID { get; set; }
public int LivingCityID { get; set; }
[ForeignKey("BirthCityID")]
public virtual City BirthCity { get; set; }
[ForeignKey("LivingCityID")]
public virtual City LivingCity { get; set; }
}
City:
public class City
{
public int ID { get; set; }
public string CityName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
To achieve what you want you need to provide some aditional configuration.Code First convention can identify bidirectional relationships, but not when there are
multiple bidirectional relationships between two entities.You can add configuration (using Data Annotations or the Fluent API) to present this
information to the model builder. With Data Annotations, you’ll use an annotation
called InverseProperty. With the Fluent API, you’ll use a combination of the Has/With methods to specify the correct ends of these relationships.
Using Data Annotations could be like this:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int BirthCityID { get; set; }
public int LivingCityID { get; set; }
[ForeignKey("BirthCityID")]
[InverseProperty("Students")]
public virtual City BirthCity { get; set; }
[ForeignKey("LivingCityID")]
public virtual City LivingCity { get; set; }
}
This way you specifying explicitly that you want to relate the BirthCity navigation property with Students navigation property in the other end of the relationship.
Using Fluent Api could be like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
.WithMany(m => m.Students).HasForeignKey(m=>m.BirthCityId);
modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
.WithMany().HasForeignKey(m=>m.LivingCityId);
}
With this last solution you don't need to use any attibute.
Now, the suggestion of #ChristPratt in have a collection of Student in your City class for each relationship is really useful. If you do that, then the configurations using Data Annotations could be this way:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int BirthCityID { get; set; }
public int LivingCityID { get; set; }
[ForeignKey("BirthCityID")]
[InverseProperty("BirthCityStudents")]
public virtual City BirthCity { get; set; }
[ForeignKey("LivingCityID")]
[InverseProperty("LivingCityStudents")]
public virtual City LivingCity { get; set; }
}
Or using Fluent Api following the same idea:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
.WithMany(m => m.BirthCityStudents).HasForeignKey(m=>m.BirthCityId);
modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
.WithMany(m => m.LivingCityStudents).HasForeignKey(m=>m.LivingCityId);
}
Sheesh. It's been a long day. There's actually a very big, glaring problem with your code, actually, that I completely missed when I commented.
The problem is that you're using a single collection of students on City. What's actually happening here is that EF can't decide which foreign key it should actually map that collection to, so it creates another foreign key specifically to track that relationship. Then, in effect you have no navigation properties for the collections of students derived from BirthCity and LivingCity.
For this, you have to drop down to fluent configuration, as there's no way to configure this properly using just data annotations. You'll also need an additional collection of students so you can track both relationships:
public class City
{
...
public virtual ICollection<Student> BirthCityStudents { get; set; }
public virtual ICollection<Student> LivingCityStudents { get; set; }
}
Then, for Student:
public class Student
{
...
public class StudentMapping : EntityTypeConfiguration<Student>
{
public StudentMapping()
{
HasRequired(m => m.BirthCity).WithMany(m => m.BirthCityStudents);
HasRequired(m => m.LivingCity).WithMany(m => m.LivingCityStudents);
}
}
}
And finally in your context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new Student.StudentMapping());
}

Asp.net Mvc Code First Many to Many with Additional Properties

As far as i know, i have two way to implement many-to-many relation in asp.net mvc using code-first.
1- Fluent Api
public class HrPerson
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HrPersonTitle> HrPersonTitle { get; set; }
}
public class HrPersonTitle
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<HrPerson> HrPerson { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<HrPerson>()
.HasMany(s => s.HrPersonTitle)
.WithMany(c => c.HrPerson)
.Map(t =>
{
t.MapLeftKey("HrPersonId")
.MapRightKey("HrPersonTitleId")
.ToTable("HrMapPersonTitle");
});
}
2-Custom Mapping Table
public class HrPerson
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HrMapPersonTitle> HrMapPersonTitle { get; set; }
}
public class HrPersonTitle
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<HrMapPersonTitle> HrMapPersonTitle { get; set; }
}
public class HrMapPersonTitle
{
public int Id { get; set; }
public int HrPersonId { get; set; }
public int HrPersonTitleId { get; set; }
public virtual HrPerson HrPerson { get; set; }
public virtual HrPersonTitle HrPersonTitle { get; set; }
public string Note { get; set; }
public bool Deleted { get; set; }
}
My questions:
If i choose second way, i am not able to reach HrPersonTitle.Name property from HrPerson model in the view. How can i reach the properties ?
If i choose the first way i can reach the HrPersonTitle.Name but i am not able to add more property in the map file ? How can i add more properties?
Regards.
When you create a M2M without a payload (just the foreign key relationships, no extra data), EF collapses the relationship so that you can query directly without having to explicitly go through the join table. However, if you need a payload, then EF can no longer manage the relationship in this way.
So, if you want to get the title, you have to go through HrMapPersonTitle:
#foreach (var title in Model.HrMapPersonTitle)
{
#title.HrPersonTitle.Name
}
Both these methods seem overkill maybe. I don't know your full intentions however I implement this all the time at work and I use the following:
public class HrPerson
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HrPersonTitle> HrPersonTitles { get; set; }
}
public class HrPersonTitle
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<HrPerson> HrPersons { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<HrPerson>()
.HasMany(s => s.HrPersonTitles)
.WithMany(c => c.HrPersons);
}
If you are using code first and you try and access either mapping within the DbContext it should Lazy Load your information and every property should be accessible.
I do have one question though. Are you sure it should be many to many, do they really have multiple titles?

MVC migration is empty

I've added a simply Product-class (shown below) but when I run add-migration it generates an empty script. I guess this is hard to troubleshoot but any idea as to why this is?
public class Product
{
public int ProductID { get; set; }
[Required]
public string Name { get; set; }
[DataType(DataType.Currency)]
public decimal Price { get; set; }
}
public class ProductDBContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
The migration file looks like this:
public partial class test : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Have you added the according Class to your DB context?
public System.Data.Entity.DbSet YourDbSetName { get; set; }
Try Clearing out _MigrationHistory (and possible also opening your Project.Data.csproj to manually delete te migrations pending)
I found the answer here: solution

Invalid object name error in DbContext subclass

I'm building an mvc application and using code first. But when I'm try access the table, the mvc throw this error:
Invalid object name 'dbo.Membro'.
My Context is:
public class JethroContext : DbContext
{
public DbSet<Area> Areas { get; set; }
public DbSet<BaseIgreja> BaseIgrejas { get; set; }
public DbSet<Igreja> Igrejas { get; set; }
public DbSet<Celula> Celulas { get; set; }
public DbSet<Membro> Membros { get; set; }
public DbSet<Distrito> Distritos { get; set; }
public DbSet<Setor> Setores { get; set; }
public DbSet<Usuario> Usuarios { get; set; }
public DbSet<Ministerio> Ministerios { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Searching on Google I found the solution, but not worked for me.
Database.SetInitializer<JethroContext>(null);
EDIT I:
Membro class
Public class Membro
{
public int Id {get;set;}
public String Name {get;set;}
public DateTime DateCreate {get;set;}
}
Invalid object name 'dbo...'.
I just realised I had the wrong Catalog selected in my Connection string. Master Blunder!!!

Resources