Entity Framework swaps navigational properties - asp.net

I am using EF with DB first approach. I am facing an issue while updating the EDMX file. Suppose I have a table InvoiceT and another table LookupT. Now, in InvoiceT I have a column InvoiceType having FK relation with LookupT. Now entity creates a navigational property in InvoiceT class with the name LookupT. So far, its good.
Now I added another column with name InvoiceStatus and FK with LookupT. Now entity creates another navigational property with the name LookupT1. But the issue here is that first navigational property LookupT is not pointing to its original data i.e. InvoiceType. Instead, its pointing to InvoiceStatus data now. Can anybody please explain to me why its behaving like this and what can I do about it?
public class InvoiceT
{
public int InvoiceId {get;set;}
public int InvoiceStatusLkpId {get;set;}
public int InvoiceTypeLkpId {get;set;}
public virtual LookupT LookupT {get;set;} // Previously pointing to Type. Now to Status.
public virtual LookupT LookupT1 {get;set;} // Pointing to Type
}
public class LookupT
{
public int LookupId {get;set;}
public string LookupValue {get;set}
public virtual ICollection<InvoiceT> InvoiceT {get;set;}
public virtual ICollection<InvoiceT> InvoiceT1 {get;set;}
}

So I figured out the issue. Seems like when EF creates the navigational properties, it does this in order of FK relation names i.e. if I have two FK relations with name RelationA and RelationB, then the navigational property for RelationA will be created first and then for RelationB. In my scenario, the relation names for my type and status were 'FK_InvoiceT_LookupT_InvoiceTypeLkpId' and 'FK_InvoiceT_LookupT_InvoiceStatusLkpId' (which SQL designer generates automatically) respectively and EF first generated the navigational property for the relation that was added later and it messed up my ordering. So all I had to do was to update relation names in order in which they were added and everything started working fine.

Related

Implement Tag database

Well hi everyone I'm kinda new on Asp.net Mvc, and need some help to improve, in my project that I'm working at, I need to register a user and in the register the user must choose some tags that are categories related to the subject of my website, the thing is that i have a database that looks like this
Tag
public int TagId{get;set;}
public string TagName{get;set;}
public string TagColor{get;set;}
TagUser
public int TagUserId{get;set;}
public int UserId{get;set;}
I read that EF constructs the tables when there is a many to many relationship, it construct the middle table automatically so in my case do i just need to have the first model and my user model? or should i use the 2 models above plus the user model, with the second approach i don't know how to relate de data i can define the TagUserId as primary key and UserId as foreignkey and relate the tables, but do i need this? or can i do that with the first approach if someone can give me a tip i appreciate a lot. :)
Ps: Sorry for my bad English
You can keep a Tags property of type IList<Tag> in your User class and a Users property in your Tag class of type IList<User>. Entity Framework will create a third table to store the many to many association between Tag and User.
public class Tag
{
public int Id {set;get;}
public string TagName {set;get;}
public virtual IList<User> Users { get; set; }
}
public class User
{
public int Id {set;get;}
public string UserName {set;get;}
public virtual IList<Tag> Tags { get; set; }
}

Code first from database doesn't create the primary key in the builder of the dbContext

I have a Sqlite database and I have installed Sqlite v1.0.99.0. To create my connection, I am using code first from database, but in the dbContext, in the method when it is used fluent to set the relationships between the entities, the primary key is not set, so I get an error when I try to run my application.
Is there any way that the primary key is set using code first from database to avoid to have to set the primary key in the entities?
Thanks.
Alas you forgot to show the class that describes your entity nor the DbContext that contains this class.
A good beginner's description can be found in "A beginner's guide to entity framework code first"
Here you can see that if you follow certain conventions you don't have to explicitly define the primary key. Entity framework does this for you.
Quite often you see the example of a database with blogs, where each blog has zero or more posts. The blog and the post will have an Id which is the primary key and the post has a foreign key to the Id of the blog.
If you don't want to specify the properties that contains the primary key, nor the ones that contain the foreign keys, define your classes as follows:
public class Blog
{
public int Id {get; set;}
public virtual ICollection<Post> Posts {get; set;}
...
}
public class Post
{
public int Id {get; set;}
public int BlogId {get; set;}
public virtual Blog Blog {get; set;}
...
}
public class MyDbContext : DbContext
{
public virtual DbSet<Blog> Blogs {get; set;}
public virtual DbSet<Post> Posts {get; set;}
}
In the code above, property Id will automatically be the primary key of Blog and Post entities. If desired you can decide to use property names Blog.BlogId and Post.PostId. Personally I don't prefer this because this would mean that all my primary keys have different identifiers.
Property Post.BlogId will automatically be the foreign key of the blog the post belongs to.

Do I need to create a DBSet for every table? So that I can persist child entities?

My EF5 model
public Layout()
{
public int Id {get;set}
public BindingList<Column> Columns {get;set}
}
public Column()
{
public int Id {get;set}
public string Name {get;set}
[Required]
[ForeignKey("LayoutId")
public virtual Layout Layout {get;set}
public int LayoutId {get;set}
}
In my context I only need to specify
DBSet<Layout> Layouts {get;set}
I dont need to specify DBSet Columns for the database to create the way I want it with both tables.
Also I am happy in my code to only ever access columns via the layout object
However i cant figure out how to persist the layout object with its columns correctly.
This question here describes how to save parent objects with children, but it would require me to create a DBSet Columns property in my context. Do I really have to do that?
It seems I can get by without having a DBSet in the context if instead of using
Context.Columns.Remove(col)
I use
Layout.Columns.Remove(col)
Context.Entry(col).State = EntityState.Deleted;

Entity Framework 4 (using EDMX), how to add a field into to model that DB does not have the field actually

I need to add a field into model that Database does not have the field actually.
Because, firstly I tried to add the field into Entity class only.
public partial class Weborder
{
(Auto Generated)
public int orderno {get; set;}
.
.
.
(Add Manually)
public string newField1 {get; set;} //this is new field that DB does not have
public string newField2 {get; set;} //this is new field that DB does not have
}
and later, when I update EDXM then EDMX remove the new fields because the database does not have the field. :(
So I add the field into EDMX model manually. (Add -> Scalar Property)
then an error occur while compiling, the error message say :
Error 1 Error 3004: Problem in mapping fragments starting at line 399:No mapping specified for properties ...
An Entity with Key (PK) will not round-trip when:...
Anybody know how to add new fields into entity class ?
Thank you!
EDITED FOR :
If your model is a representation of your database and in the database you don't have the field, why do you want to add it manually?
=>
When retrieve data, the return type of object is the entity class.
and before passing data from controller to view, I need to add more data(fields) into the IQueryable result.
ex)
public DbSet<WEBORDERLN> WEBORDERLNs { get; set; }
//repository
public IQueryable<WEBORDERLN> WebOrderLns
{
get { return context.WEBORDERLNs; }
}
and now I get the weborderln data in controller. and before passing view, I need to
add extra data into the result.
var data = webOrderLnRepository.WebOrderLns.Where(e => e.PICKNO == OrderNo).ToList();
foreach (WEBORDERLN weborderln in data)
{
weborderln.[NEW FIELD] = "EXTRA DATA"; //// FOR THIS, I NEED TO ADD NEW FILED INTO ENTITY CLASS
}
//return data
I hope it could explain the question :)
Thanks again.
You must create a new partial part of your entity class (in the new .cs file) and add new fields to that class. You must not modify the partial part created by autogeneration because autogenerated files will be overwritten every time you change EDMX file. You also must not include the field in EDMX because EDMX defines your mapping to database = it contains only fields in database.
Create a new file WebOrderPart.cs in the same assembly and namespace as your autogenerated classes containing:
public partial class Weborder
{
public string newField1 {get; set;}
public string newField2 {get; set;}
}
Dosn't [NotMapped] work.
[NotMapped]
public string newField1 {get; set;}
First of all, you shouldn't modify the data model file. This file represents your data.
Second, you shouldn't be returning your data model objects/collections from your Repository. This is a very bad practice because you are creating a dependency between the Controller/View and the Model. I suggest you create custom Model objects that contain the properties you need in your View, map your entities to those Model objects and only return Model objects or collections of Model objects from your Repository.

EF Code First: Object with One-to-Many and M-T-M of same classes fails to generate M-T-M in db

I have the following classes (shortened)
Game
{
public int id {get;set;}
public virtual ICollection<Player> Players {get;set;}
public virtual Player Owner {get;set;}
public virtual ICollection<Character> Characters {get;set;}
}
Players
{
public int id {get;set;}
public virtual ICollection<Game> Games {get;set;}
}
Characters
{
public virtual ICollection<Game> Games {get;set;}
}
For whatever reason, my database generates a one-to-many link for Game-Players.
It does, however, create one for games-characters.
I have no idea why this would be, other than perhaps the one-to-many is screwing with it in some way!
Your Game class has two navigation properties to the Player class. EF doesn't know which one to map to the target Player.Games. Because of that it decides that there are actually three relationships:
Game.Players <-> not exposed
Game.Owner <-> not exposed
Player.Games <-> not exposed
And the fourth relationship is
Game.Characters <-> Character.Games
For the last one EF detects the right ends of the relationship because they are not ambiguous.
The easiest way to fix that is to give EF a hint which of the two navigation properties on Game refering to Player actually belongs to Player.Games:
public class Game
{
public int id {get;set;}
[InverseProperty("Games")]
public virtual ICollection<Player> Players {get;set;}
public virtual Player Owner {get;set;}
public virtual ICollection<Character> Characters {get;set;}
}
Now the result are the expected three relationships:
Game.Players <-> Player.Games
Game.Owner <-> not exposed
Game.Characters <-> Character.Games
Instead of using the [InverseProperty] attribute you can also specify this in Fluent API by explicitely mapping a many-to-many relationship between Game.Players and Player.Games.
The public int id is the default variable name for EF Code first key values. It does recognize this implicitly.
This key value is omitted in Characters, and therefore handled differently.

Resources