I've noticed a lot of github project using models that extend Entity.
I'm following a tutorial and it doesn't do this. Its just a plain class.
public class Seller
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string URL { get; set; }
}
https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-4
Then here I found models that extend Entity:
https://github.com/IshtiaqueIrteza/Movie-Review-website/blob/master/BackEnd/Movie%20Review%20Website/MRWEntity/Category.cs
Are there multiple version of EF and which one should I use if I'm working with Web API?
Entity class which exists in the github repository you provide, is just a base class for entities created by hand. It is up to you creating a base model or not for all your entities.
Of course there are multiple versions of EF but it is not related with your question here.
Related
I’m building a hiring process with EF Code First version 6.0. I’ve got the following (highly abbreviated) inheritance hierarchy that’s implemented using Table-per-Type:
[Table("Person")]
public class Person
{
[Key]
public int PersonId { get; set; }
[StringLength(30)]
public string FirstName { get; set; }
[StringLength(30)]
public string MiddleName { get; set; }
[StringLength(30)]
public string LastName { get; set; }
}
[Table("Applicants")]
public class Applicant : Person
{
//Various Applicant properties
[StringLength(256)]
public string UserName { get; set; }
}
[Table("Employees")]
public class Employee : Applicant
{
public DateTime HireDate { get; set; }
[StringLength(20)]
public string WorkPhone { get; set; }
[StringLength(30)]
public string JobTitle { get; set; }
//Various other Employee Properties
}
Whenever I execute the following query in LINQPad:
Applicants.Where(x => x.UserName == "johndoe999")
the query returns fields associated with the derived class Employee (HireDate, WorkPhone, JobTitle) which I wasn’t expecting. I’d obviously want it to omit “Employee” related fields when all I’m asking for are applicants.
This doesn’t happen whenever I implemented this same hierarchy as table-per-hierarchy. It should give me the same behavior with Table-per-type, shouldn’t it? Is there something else I need to do to enable this behavior?
I've seen some references to this issue such as (Entity Framework Table Per Type Performance) however this is from '11 in relation to a much older version of EF.
Apparently this isn't supported even as of EF 6.1. I found the following work item on codeplex:
https://entityframework.codeplex.com/workitem/2332
Here is a link to an article explaining a workaround by mixing Dapper ORM with Entity Framework. According to the author performance increases dramatically.
http://blog.falafel.com/how-to-improve-the-performance-of-tpt-inheritance-mapping-in-entity-framework/
Here is a discussion on EF's github page regarding EF 7 version 1.0 which actually omitted TPT altogether but they state they eventually will put TPT back into EF 7. I just skimmed the article but it isn't clear whether they will address the performance issue with TPT when they add it to EF 7 or if it will work the same as it did in version 6.1.
I will either use Dapper ORM or find a different approach to modeling my data.
I am learning ASP.NET MVC. And In order to create PK and FK I have added some code in models in .cs file as below
public class Courses
{
public int CourseID { get; set; }
[Key]
public string CourseName { get; set; }
public string Description { get; set; }
public int Duration { get; set; }
public virtual ICollection<Instructors> Instructors { get; set; }
}
public class Instructors
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CourseName { get; set; }
[ForeignKey("CourseName")]
public virtual Courses Courses { get; set; }
}
My question is then what is the significance of Fluent API. I have successfully created PK and FK using above code in model. Then what is Fluent API and why it is needed?
Entity framework Fluent Api is an alternative way to define database schema using Entity framework Code First approach. The syntax that you used in your question uses data annotations which is other common approach.
The major advantage of FluentApi is that you don't have to have actual access to your model classes in order to decorate them. For example when you have your models in separate assembly decorating them with annotations is simply impossible. On the other hand by using EF FluentAPI you can easily do it with something like:
modelBuilder.Entity<Courses>().HasKey(c => c.CourseID);
At the bottom line both approaches generate exactly the same database schema.
So if you prefer to use data annotations and your project structure allows it, you can use it without any doubts. In those cases when you can not use the data annotations approach and you still want to use Code First approach, FluentApi is the right way to look at.
I'm trying to implement various tables that inherent a groups table. When I generate the database from the model it comes out as type-per-table instead of type-per-inheritance like I would like.
I have:
Group set to abstract
Each group type table is mapped to Group conditionally when type(column) = a different int for each table
Can anyone point me in the right direction for what I need to do to change this to type per inheritance?
EDIT: by request via comment here is my db set for group, and none of the group types of a dbset
public DbSet<Group> Groups { get; set; }
Here are the generated classes:
Group:
public abstract partial class Group
{
public Group()
{
this.GroupHierarchies = new HashSet<GroupHierarchy>();
this.GroupHierarchies1 = new HashSet<GroupHierarchy>();
this.NetworkActions = new HashSet<NetworkAction>();
this.PermissionAssignments = new HashSet<PermissionAssignment>();
this.UserProfiles = new HashSet<UserProfile>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Acronym { get; set; }
public string Description { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
public virtual ICollection<GroupHierarchy> GroupHierarchies { get; set; }
public virtual ICollection<GroupHierarchy> GroupHierarchies1 { get; set; }
public virtual ICollection<NetworkAction> NetworkActions { get; set; }
public virtual ICollection<PermissionAssignment> PermissionAssignments { get; set; }
public virtual ICollection<UserProfile> UserProfiles { get; set; }
}
One of the group types:
public partial class HoaManagementCompany : Group
{
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
The other group type, there will be many more in the future but only these two until I get it to work.
public partial class HoaAttorney : Group
{
public string Address { get; set; }
}
When I generate the database from the model...
Are you using Model-First strategy? This unfortunately would make it difficult to get TPH inheritance for your model (which would be easy for Code-First or Database-First strategy).
(Default inheritance mapping for Code-First is TPH, so you should not have your problem with Code-First.)
Out of the box TPH is not available with Model-First. The default inheritance strategy for Model-First is TPT and there is no easy way to switch to TPH in the model designer:
It is possible to map to a TPH inheritance using Model First but you
would have to write your own database generation workflow which is
complex. You would then assign this workflow to the Database
Generation Workflow property in the EF Designer. An easier alternative
is to use Code First.
There is an additional tool from Microsoft - the Entity Designer Database Generation Power Pack - which supports TPH database generation workflow for Model-First. But the problem is that it doesn't look very well maintained (last update from May 2012) and it doesn't support Visual Studio 2012. But if you use VS 2010 you can try it.
You should only use your Groups DBSet for TPH.
Also make sure you aren't adding Table annotations to the poco classes
Try following this blog, it worked for me in the past.
Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH).
Also talks about Table per Type (TPT) and Table per Concrete class (TPC) Inheritances.
I'm afraid that if I include my code this post will get too long and too complicated, so I'll try and explain my problem. If however you'd like to see some code illustrating this problem, I'll be happy to add it afterwards.
I have a project, MVC4 project (Website.Web) that used entity framework code first. My entity classes is in a seperate project: Website.Domain
I have a NewsPost class:
public virtual int Id { get; set; }
public virtual string Subject { get; set; }
public virtual string Content { get; set; }
public virtual string ImageName { get; set; }
public virtual DateTime CreateTime { get; set; }
public virtual int CreatedById { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
And my comments class looks like this:
public virtual int Id { get; set; }
public virtual int CreatedById { get; set; }
public virtual DateTime CreatedTime { get; set; }
public virtual string Content { get; set; }
Now in my MVC project, I have entity framework set up with some repository classes and ninject to seperate everything from my controllers. And when I do a "GetAll()" on my newsposts. The NewsPost.Comments will be filled with the comments that's associated with this newspost. It all works perfectly.
Now I got the idea that I'd like to use webapi, so I set up a new MVC basic project. I removed the views folder, and removed the models folder. Then I setup all the repositories here as well along with my entity framework dbcontext class. And enabled migrations on the project to allow me to use entity framework code first in the same fasion as the Website.Web project. I also referenced the same Domain classes as the web project.
Now here comes the problems. I tried doing a GetAll() on the newsposts, but when I inspect the list returned by GetAll(), I see that though it fetches all the news in the database, the COMMENTS are null. I'm pretty sure I have the Website.API set up the same way as my Website.Website.Web - So what am I missing?
I hope I have explained well enough. Again if you need any additional code or I need to clarify some points, I'll happily do this, I just didn't wanna make the question more complicated than it already is with too much code.
I am using the Entity Framework code first for data access and I have a Company class which has a collection of Employees. The Employee class also has a Company property.
I would like to be able to serialize a Company and include the list of employees in the serialization.
Here is Company:
public class Company
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime? Established { get; set; }
public virtual IList<Employee> Employees { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}
Here is Employee
public class Employee
{
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public virtual Company Company { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}
I get a serialization Exception "Self referencing loop detected for type" when I try to serialize a Company object.
Thanks.
I think they have fixed this in the latest version.
Check out the help docs under the section "Serializing and Deserializing JSON -> Serialization and Preserving Object References".
Set this setting when initializing the JSON.Net Serializer:
PreserveReferencesHandling = PreserveReferencesHandling.Objects;
So an example would be this:
var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };
string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);
I verified that this works with my code first solution, and a circular reference in the navigation properties. If you look at the resulting JSON it should have "$id" and "$ref" properties everywhere.
Updated Answer
You can either:
reconfigure json.net to ignore
selfreference loops
use the [JsonIgnore] Attribute
use a custom converter that remove
the navigation in the child
or you can use Data Transfer Objects
In case this helps anyone, I thought I'd document how we resolved this same error for our purposes when using Entity Framework 4.3.1 and JSON.Net 4.5.3.
We are using the Database First DbContext approach. For our needs, we could resolve it using the [JsonIgnore] attribute. The trick is just that since changes to the automatically generated entity classes are overwritten when you refresh from the database, with Database First you can add the attributes using the "metadata buddy class" approach given in this StackOverflow post.
Below is a code excerpt. We had a "Query" object (class Query) that had relationships to "Company" and "User" objects. In a new class file, we declare the partial class with a [MetadataType] attribute, and then in the QueryMetadata class we specified, we annotate the members we want to ignore— namely the public virtual members that EF4.x adds to express the relationships (a.k.a. navigation properties).
The Query entity also has foreign key fields (named FK_User and FK_Company in our case). These fields do not need the [JsonIgnore] attribute— they can be serialized with their foreign key values.
[MetadataType(typeof(QueryMetadata))]
public partial class Query
{
}
public class QueryMetadata
{
[JsonIgnore]
public virtual Company company { get; set; }
[JsonIgnore]
public virtual User user { get; set; }
}
However, if we actually had to also serialize the related Company or User objects, we'd hit a brick wall! The approach suggested by John Bubriski here wouldn't work for us since we want to rely on Entity Framework change tracking.
If you are getting this error using WebApi you can put the following in WebApiConfig.cs so json.net ignores circular refs
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Microsoft : Loop Reference handling in Web API
If you're using WebAPI EntityFrameworkCore 2.0 this solution doesn't work, you need to set it on Startup.cs->ConfigureServices:
.AddJsonOptions(options => {
var settings = options.SerializerSettings;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});