JQgrid / Entity Framework Issue with entities that have a relationship - entity-framework

I have an entity that has a relationship with another entity. I am able to search on columns that are in the main entity, and include columns from the relationship entity. But I need to be able to filter the list (search) on columns that are not in the relationship entity.
for example
the Invoice Entity contains a customerId property, and is related to the Customer Entity which contains the customerName property
I need to be able to search / filter the grid by customerName.
I am new to entity framework, please help.
thanks
Carl

Your relation is 1->1. In these cases I usually return a custom class to the grid that has all the columns I need, including joins with other tables.
So basically what you need is to create a custom linq query with your resultset.
The mais query should follow this example:
var q = from i in ctx.Invoices
join c in ctx.Customers on i.CustomerID equals c.CustomerID
select new{InvoiceID=i.InvoiceID, InvoiceDate=i.Date, CustomerName=c.Name};
Now, assuming we receive a CustomerName variable with the string to filter by c.Name we could do:
if(!string.IsNullOrEmpty(CustomerName))
{
q = q.where(c => c.Name.ToLower().Contains(CustomerName.ToLower()));
}
Notice that I'm performing a ToLower() operation and a Contains, this will beahave as a LIKE ingnoring case sensitivity and searching for the string anywhere in the Customer Name.
At the end you'll return the q.ToList() serialized for the jqGrid...

Related

Laravel Eloquent Query Builder (with JOIN)

Tables
VENDOR
id name approved
PRODUCT
id name price instock fky_prod_vendor_id
Relationship
VENDOR(hasMany products()) <- (one-to-many) -> (hasOne vendor())PRODUCT
Query
How can I get all the products in-stock of a approved vendor using Eloquent given that the relationships are defined in Model?
My SQL is as following, but I need to use Eloquent relationship to achive the following.
select product.id
from product, vendor
where product.fky_prod_vendor_id = vendor.id
and vendor.approved = 'y'
and product.instock > 0
Thanks
K
As relationships are present, we can achieve this using Querying Relationship Existence method whereHas as rightly pointed out by #svrnm
PRODUCT::where('instock','>',0)
->whereHas('vendor', function ($query) { // Using Eloquent Query Existence, first parameter is name of relationship method, inside function is where clause on related model
$query->where('approved','y');
})->get();
That's magic of Laravel
Thanks
K

Why does "select many" on query syntax not work with join

An Invoice has many products and a product can have many X (X shall not be important here)
var query = from i in invoices
join prod in i.products on i.id equals prod.InvoiceId
select new MyClass{ Id = i.id, more props }
Why does the join not work?
I get the error that "i.product" The "i" here does not exist in the current context.
join is for when you have two separate collections, where you want to compare some properties of the various elements of those collections. You can use it when you have a separate unfiltered collection of products, and you want to find products that match on invoice ID. For instance, you might use it if you didn't define any navigation properties.
That's not what you're after here: you do have a navigation property, and by using that, Entity Framework will have set up things so that i.products only contains the matching products. You don't need to link on invoice ID manually.
var query = from i in invoices
from prod in i.products
select ...;

Selecting columns from different entities

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.

EF LINQ to Entites query for a Many to Many relationship

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.

Whats the best way to join two tables with no database relationship using EF?

Ok, lets say you have two tables: Order and OrderLine and for some reason they do not have a foreign key relationship in the database (it's an example, live with it). Now, you want to join these two tables using Entity Framework and you cook up something like this:
using (var model = new Model())
{
var orders = from order in model.Order
join orderline in model.OrderLine on order.Id equals orderline.OrderId into orderlines
from ol in orderlines.DefaultIfEmpty()
select new {order = order, orderlines = orderlines};
}
Now, the above will produce orders and orderlines, left-joined and all, but it has numerous issues:
It's plain ugly
It returns an anonymous type
It returns multiple instances of the same order and I you have to do Distinct() on the client side because orders.Distinct() fails.
What I am looking for is a solution which is:
Pretty
Returns a statically well-known type instead of the anonymous type (I tried to project the query result, but I got into problems with the OrderLines)
Runs Distinct on the server side
Anyone?
Even if the database tables do not have a foreign key relationship setup, you can configure Entity Framework as if they do.
Add an OrderDetails navigation property to your Order class and then just query Orders.