public class Link
{
public virtual Category Category { get; set; }
}
public class Category
{
public Category(){Links = new List<Link>}
public virtual IList<Link> Links {get; set;}
}
My problem is when I wanna create Link with reference to Category I got a error with foreign key.
I try to use fluent api, get threw repo category but still the same problem.
EF want to create new object of Category.
To pass data I get to controller second repo(category) and pass to viewbag data.
4 hours spent to find solution but still I've got nothing, could someone explain it to me how it work that I cant pass that :/
Both of your classes need properties that can be mapped to primary keys. This is most commonly done with an int called ID...
public class Link
{
public int ID { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
public int ID { get; set; }
public Category(){Links = new List<Link>}
public virtual IList<Link> Links {get; set;}
}
Related
I'm using entity framework code first approach
I have a class
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public Person Director { get; set; }
public virtual ICollection<Person> Actors { get; set; }
}
and a class
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
When the database is created I get one table Movies with Id, Title, Director_Id and a table Person with Id and Name.
I expect to have a table Movies_Persons with columns Movie_Id and Actor_Id
How can I achieve this?
Your Problem is, that you don`t tell the Person Class, that there can be multiple Movies per person.
So by adding the following line in your person class:
public virtual ICollection<Movie> Movies { get; set; }
Your entity knows that both your classes can have multiple references to the other class.
To fulfill this requirement Entity Framework will create a third table with Movie_ID and Person_ID.
If you want more informations just look for:
Entity Framework - Many to many relationship
or follow this link:
http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx
You can check out the other articels on that page too, if you are new to entity framework.
UPDATE:
Sorry i missed, that you are already have another reference to your person table.
Here you have to tell your entity framework, which way you want to reference the two tables by fluent api.
Check out this stackoverflow answer. That should do the trick.
You have to insert this code into your OnModelCreating Function of your DbContext Class.
So your final code should look like this:
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public virtual Person Director { get; set; }
public virtual ICollection<Person> Actors { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Movie> Movies_Actors { get; set; }
public virtual ICollection<Movie> Movies_Directors { get; set; }
}
And in your OnModelCreating add following code:
modelBuilder.Entity<Movie>()
.HasMany(a => a.Actors)
.WithMany(a => a.Movies_Actors)
.Map(x =>
{
x.MapLeftKey("Movie_ID");
x.MapRightKey("Person_ID");
x.ToTable("Movie_Actor");
});
modelBuilder.Entity<Movie>()
.HasRequired<Person>(s => s.Director)
.WithMany(s => s.Movies_Directors);
I don't have the possibility to test the code, but that should do the trick.
If you have to do some adjustments to make it work, plz add them in the comments, so other ppl can benefit from it.
I have a class Request, that I would like to have two properties, BudgetHolder and FinancialController, both of a single type - Employee. I'm trying to do this in using a Code-First approach to the database in MVC 4.
When I use the update-database command I get the following error
Error: The new name 'BudgetHolderId' is already in use as a COLUMN name and would cause a duplicate that is not permitted.
Ultiamtely I'm to create a page that will allow a Request to be created to show two drop downs with a list of Employees in each, but currently all that is shown are textboxes for BudgetHolderId and FinancialControllerId
My current code is as follows.
public class Request
{
public virtual int BudgetHolderId { get; set; }
[ForeignKey("BudgetHolderId")]
public virtual Employee BudgetHolder { get; set; }
public virtual int FinancialControllerId { get; set; }
[ForeignKey("FinancialControllerId")]
public virtual Employee FinancialController { get; set; }
}
So, I'm still not certain why the above did not work, but my solution was to change the declaration above to the following
public class Request
{
public virtual int BudgetHolderEmployeeId { get; set; }
[ForeignKey("BudgetHolderEmployeeId")]
public virtual Employee BudgetHolder { get; set; }
public virtual int FinancialControllerEmployeeId { get; set; }
[ForeignKey("FinancialControllerEmployeeId")]
public virtual Employee FinancialController { get; set; }
}
I would guess that there is an implicit item called BudgetHolderId and FinancialControllerId that was preventing me from declaring my own variables/columns with the same names.
Either way, the above now compiles, and when a new RequestController is generated the existing Employees are included as drop down lists.
I have two related entities called DataTag and TagSource that look like the following:
public class DataTag : BaseModel
{
[Column("DataTagId")]
public override Guid ID { get; set; }
public string Tag { get; set; }
public Guid TagSourceId { get; set; }
public TagSource TagSource { get; set; }
}
public class TagSource : BaseModel
{
[Column("TagSourceId")]
public override Guid ID { get; set; }
public string Description { get; set; }
public bool IsInternal { get; set; }
public string Source { get; set; }
public ICollection<DataTag> DataTags { get; set; }
}
I am allowing the user to Include the navigation properties through the url like "/api/DataTags?Include=TagSource". The problem is when I include the TagSource, it also includes the collection of DataTags in that object which I don't want unless the user specifies it (For example "/api/DataTags?Include=TagSource.DataTags". Is there any way to stop that property from being loaded when I include the TagSource? I have tried making the properties virtual and turning lazy loading off globally but that didn't work. The reason I haven't marked them virtual is because I am using AutoMapper and I only want to include the navigation properties that the user specifies.
As in the comments you need to create a DTO object. There is a good article here detailing how to do this with WebAPI
http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-5
Edit.
The problem with this is you will need a lot of different DTO objects for each possible outcome which could become messy. If your return type is JSON you can add this attribute to your properties:
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
Firstly : Apologies for my English.
Secondly : I had the same issue with a code first database model that creates foreign keys this way : public virtual Collection<Object> Objects {get; set;}
and I found a workaround by setting the property setter as private:
public virtual Collection<Object> Objects {get; private set;}
Then the EF cannot populate the Objects collection because with a private set you can only assign a value in constructors.
I have a issue with updating value on a foreign key which is inheriting from another class. I am working with detached object in Entity Framework, so I'm using graphdiff to handle it.
I've simplified the code to make it easier to read
Project class:
public class Project
{
public Guid Id { get; set; }
public virtual List<Activity> Activities { get; set; }
}
Activity class:
public class Activity
{
public Guid Id { get; set; }
public String Name { get; set; }
public virtual Company Company { get; set; }
}
SurfingActivity class:
public class SurfingActivity : Activity
{
public String Comment { get; set; }
public virtual Weather Weather { get; set; }
}
The update context using graphdiff:
public void UpdateActivity(Project project)
{
this.UpdateGraph(project, map => map
.OwnedCollection(p => p.Activities, with => with
.AssociatedEntity(a => a.Company)
)
);
}
I'm only able to associate the Company property in Activity but not the Weather of SurfingActivity. When I pass along values for SurfingActivity does Id, Name, Company and Comment get saved in the Activity table and the SurfingActivity table but not weather. Does anyone have any suggestion how to solve this without having to create a new property on Project that contains a list with surfingActivity
I asked andypelzer in GraphDiff and this is currently not supported. My work around, which would work in this case (but not if the entities becomes even more nested) is to add the foreign key property as datatype it is and data annotation ForeignKey to the foreign key with the entity, like this:
public System.Guid? Weather_Id { get; set; }
[ForeignKey("Weather_Id")]
public virtual Weather Weather { get; set; }
Link to question: https://github.com/refactorthis/GraphDiff/issues/112
I asked a question recently, and quite frankly, from the answer that was given, I am second guessing my entire strategy/how I design the classes and database.
I have not yet used the virtual keyword, nor Icollection at all in any of my Entity Framework projects, and quite frankly, after reading about it in some of the examples I do not fully understand why it is needed, or how it works.
In a sample application, I have a simple design where there are three lists - people, notes and pictures. The relationships are such that a person can own multiple notes and pictures, as well as people having a logo which is a picture.
public class Person
{
public int ID { get; set; }
public string name { get; set; }
public Picture logo { get; set; }
}
public class Note
{
public int ID { get; set; }
public string Text { get; set; }
public Person Owner { get; set; }
}
public class Picture
{
public int ID { get; set; }
public string Path { get; set; }
public Person Owner { get; set; }
}
When I want to select a list of notes that a person owns, I simply perform db.Notes.Where(x=>x.owner=="y") on the notes object. I think I understand that if I were to use Icollection on the person class, I could instead perform something along the lines of db.person.select(x=> x.notes) to retrieve all the notes. Am I correct in this thinking?
If you were in my position with the relatively simple example above, how would you build the classes (involving ICollection, virtual or anything else)?
In addition and most importantly, the above is just an example, however in my actual application, I have used a very similar structure where I use my custom type as the "connector"/Foreign Key.
In many examples I have been reading, (in the above example) they would be using public int OwnerID instead of public person Owner. This has really thrown me and I am questioning my entire EF strategy. What are the differences?
Any advice would be greatly appreciated.
I think you are making this more difficult that is needed. If you were laying out regular classes you would relate them to each other rather than finding related id's and loading them separately which you are doing in your example.
public class Person
{
public int ID { get; set; }
public string name { get; set; }
public ICollection<Note> Notes { get; set; }
public ICollection<Picture> Pictures { get; set; }
public Picture logo { get; set; }
}
public class Note
{
public int ID { get; set; }
public string Text { get; set; }
public Person Owner { get; set; }
}
public class Picture
{
public int ID { get; set; }
public string Path { get; set; }
public Person Owner { get; set; }
}
So now say you have gotten your person object using the query
var person = _context.People.Where(m=>m.ID=randomIntWeWant).First();
We can get all related items as properties.
For Notes
person.Notes
For Photos
person.Photos
ICollection is related to lazy loading. By declaring a property as ICollection on one side, your are saying you have a many-to-one relationship between the objects. If you declare a property as ICollection on both sides, you are saying it is a many-to-many relationship. EF takes care of creating the tables that track that relationship.