Suppose I have
table Person
table Employee, which inherits Person.
I want to get a list of Person, regardless if this Person is Employee or not. How do you get entity framework to do that without joining the Employee table? C# is what I'm using. Thanks.
You need to make sure that you don't implicitly use any information from Employee.
If you do this:
var people = Context.People.ToList();
... Then me Entity Framework will initialize new instances of type Employee for those people who happen to be employees. This is because when you store an Employee in the database, you generally expect to get an Employee back when you select the same item.
Nor, for that matter, can you tell the Entity Framework to give you a Person when the stored value is an Employee. The Entity Framework will never give you back an incorrect entity type.
However, if you do just want to read the one table, there is a way to do that: Select the data from Person into a non-entity types, such as an anonymous type:
var people = Context.People.Select(p => new { Name = p.Name }).ToList();
Related
I don't know whether I should be drawing parallels, but unfortunately, that's the only way I can express my issue.
In SQL, suppose we have two tables:
Employee with columns Employee ID, Employee Name, Dept. ID
Deptartment with columns Dept. ID, Dept Name
The Dept ID. in the Employee table is a foreign key with that in the Department table.
Now suppose I want to fetch the following columns:
Employee ID, Employee Name, Department Name
using a SQL such as:
SELECT A.EMPLOYEE_ID, A.EMPLOYEE_NAME, B.DEPT_NAME
FROM EMPLOYEE A, DEPARTMENT B
WHERE A.DEPT_ID = B.DEPT_ID
How would one do this using Core Data in Swift? I guess I'm getting confused by only seeing references to
NSFetchRequest(entityName: entityName)
where the entityName refers to a single entity (table in relational DB lingo)
I'd really appreciate any pointers or examples that can help me clear my doubts.
Thanks
It is certainly possible to create a fetch request that is equivalent to your SQL query. More complex queries can be difficult if not impossible to achieve with a single fetch request. But I recommend trying NOT to draw parallels between CoreData and SQL, at least until you have got to grips with how it works.
To take your example, in the CoreData view of the world, Employee would be an entity with a relationship to another entity, Department. A fetch request based on the Employee entity will return an array of Employee objects, and (assuming you create subclasses of NSManagedObject for each entity) you can access the attributes with simple dot notation:
let employeeName = myEmployeeObject.employeeName
But you can use the same notation to traverse relationships equally easily:
let departmentName = myEmployeeObject.department.departmentName
You don't need to worry about joins, etc; CoreData handles that for you.
Now, suppose you try to do it "the SQL way". You can construct a fetch request based on the Employee entity, but specify "properties to fetch" which likewise traverse the relationship:
let fetch = NSFetchRequest(entity:"Employee")
fetch.propertiesToFetch = ["employeeID", "employeeName", "department.departmentName"]
For this to work, you would need to specify the "resultType" for the fetch request to be DictionaryResultType:
fetch.resultType = .DictionaryResultType
The results from this query would be an array of dictionaries containing the relevant keys and values. But the link with the underlying objects is lost. If you subsequently want to access any details from the relevant Department (or even the Employee), you would have to run a new fetch to get the object itself.
trying to work out how to do LINQ to Entities query for a many to many relationship which has a junction with fields table.
Below are the Domains models (I am using View models, but keeping it simple for this example).
Student Domain model
StudentID (PK)
ICollection<StudentCourse> StudentCourses
StudentCourse Domain model
StudentCourseID (PK)
StudentID (FK)
CourseID (FK)
ForAdult
ForSeniour
Description
Course Domain model
CourseID (PK)
ICollection<StudentCourse> StudentCourses
Note:
Since the junction table (i.e. StudentCourse) contains fields other than the two foreign keys, EF will create an entity for this.
Lazy Loading
I've got this working for lazy loading. The Navigation properties have been declared with the 'virtual' keyword.
The Query way - works!
var student = (from s in context.Students
where s.StudentID == id
select s).SingleOrDefault<Student>()
The Method way - works!
Student student = context.Students.Find(id);
Projection
BUT, I would prefer to do this with projection, for performance reasons, i.e. less trips to the database.
I'm really stuck on how to write up the LINQ to Entities query to return 1 student with (1 or) many StudentCourses.
I don't understand thoroughly how the Entity should be shaped, if you know what I mean.
For example, I've tried:
var myvar = from s in context.Students
from sc in s.StudentCourses
where s.StudentID == id
select s
What I require is to return an entity of Student with a collection of StudentCourses which could then be assigned to a Student and passed to the View model, then to the View.
Really would appreciate any help, as I've spent alot of time trying to solve this.
Also as a side note, I'm using the SingleOrDefault() method to cast the results of the var (IQueryable I think) to type Student. Is this the preferred way to cast?
You can get EF to eagerly load the related entities by using the Include method.
So using your LINQ example:
var student = (from s in context.Students
where s.StudentID == id
select s).Include("StudentCourses").FirstOrDefault();
And using extension methods:
var student = context.Students.Include("StudentCourses").FirstOrDefault(id);
The Student instance that is returned will have the StudentCourses collection populated with related entities. This should invoke only one SQL query that joins the tables together.
To answer your aside question: I prefer to use FirstOrDefault most of the time as above. The difference is that SingleOrDefault will expect exactly one result and throws an exception otherwise, whereas FirstOrDefault will return null if a student is not found.
Also, as the cast to Student is implicit, you don't need the <Student> type parameter.
so the story is very simple.
I have one table called Products and another Called categories. In addition, i have another table called ProductCategories that hold the relationship of catetories to their corresponding products (i.e, the table has two columns, ProductId, ColumnId).
For some reason, after adding all those table to my entity model, i don't have "Access" to it, hence i can do myentityModel.ProductCategories, so i could relational items between those two tables.
And yes, the ProductCategores table is added as "Association" to the entity model. i don't really understand that.
EDIT:
I do see that as part of creating new "Product" i can pass EntityCollection of "Category". So i do query from my entity model for a list of the matching categories that the user selected (on the webpage). so for example, i get (after query the model), an Objectset of "Category". However, i encountered two issues:
the 'AddObject' accept only EntityCollection, hence i need to re-create a set and then add all the objects from the ObjectSet to the entityCollection, in this process i need to detach it from the previous model and add it to the new collection. if not, i get an exception.
when i do the SaveChanges, i see that i get an exception that it was actually trying to Create new Category rather than adding new ProductCategory. again, am i missing something here?
Thanks.
This sounds like a Many-to-Many relationship. In your entity model, you don't need to declare the join table as a separate entity. Instead, you configure the relationship between the Products and the Categories as a Many-to-Many and add metadata about the join table. In Hibernate, you would have:
#ManyToMany(targetEntity=Categories.class, cascade={CascadeType.ALL}, fetch = FetchType.LAZY)
#JoinTable(name="tb_products_categories",
joinColumns=#JoinColumn(name="category_id"),
inverseJoinColumns=#JoinColumn(name="product_id")
)
#IndexColumn(name="join_id")
public List<Categories> getCategories() {
return categories;
}
When you query, the ORM layer takes care of determining SQL and traversing table joins.
OK, I have 3 tables, call them:
Person
PersonID
Name
Store
StoreID
Name
PersonStore
PersonID
StoreID
Now, I have a form which allows you to add stores to a person. However, I am getting the store ID back from the form. I don't really want to do a query to get the store object from Entity Framework. I just want to add to the table using the StoreID and the Person object which I have.
By default in EF this join table won't appear as an entity instead you'll get a many to many relationship which will show up as two navigation properties
i.e.
Person.Stores
Store.People
If you want to build a many to many relationship without retrieving the entities then attaching stub entities is the best way.
var person = // you already have the person
var store = new Store{StoreID = 5} // you know the storeID
ctx.AttachTo("Stores", store);
ctx.AttachTo("People", person); // assuming the person isn't already attached
person.Stores.Add(store);
ctx.SaveChanges();
The only problem with this code is it will fail if the relationship already exists, so you need to be sure you are creating a new relationship
For more on using Stub entities like this check out my post.
Hope this helps.
Alex
Edit from OP:
Since I am using EF4, I used the following code to remove the string from the attach (thanks to tip 13 from the link).
var person = // you already have the person
var store = new Store{StoreID = 5} // you know the storeID
ctx.Stores.Attach(store);
person.Stores.Add(store);
ctx.SaveChanges();
I am just starting to use the Entity Framework 4 for the first time ever. So far I am liking it but I am a bit confused on how to correctly do inheritance.
I am doing a model-first approach, and I have my Person entity with two subtype entities, Employee and Client. EF is correctly using the table per type approach, however I can't seem to figure out how to determine what type of a Person a specific object is.
For example, if I do something like
var people = from p in entities.Person select p;
return people.ToList<Person>();
In my list that I form from this, all I care about is the Id field so i don't want to actually query all the subtype tables (this is a webpage list with links, so all I need is the name and the Id, all in the Persons table).
However, I want to form different lists using this one query, one for each type of person (so one list for Clients and another for Employees).
The issue is if I have a Person entity, I can't see any way to determine if that entity is a Client or an Employee without querying the Client or Employee tables directly. How can I easily determine the subtype of an entity without performing a bunch of additional database queries?
Use .OfType<Client>() in your query to get just the clients. See OfType.
e.g. entities.Person.OfType<Client>() ...
Use is to test if a Person object is a specific sub-class, e.g. if (p is Employee) ...
BTW why isn't it entities.People? Did you not select the pluralization option?