Dynamic IQueryable Join Query - c#

Background:
Given the following two entities joint through one to one relationship:
public partial class Parent
{
public long Id { get; set; }
public string Email { get; set; }
public virtual Details Details{ get; set; }
}
public partial class Details
{
public long Id { get; set; }
public long ParentId{ get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public virtual Parent Parent { get; set;}
}
And having the following Query model:
public class Query
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? Dob { get; set; }
}
Question
How can I apply the Query as IQueryable on the Parent (or Details) entity?
Notes based on the use case I have:
Query class can't have two sub-classes for Parent and Details (it should be flattened)
DB SQL query should fetch results that matches both conditions in Parent and Details (if condition fail for details, then parent shouldn't be in the results).
There might be long list of optional fields in Query model. It means that the DB query should be dynamic and smart enough to know how to build the query and to know each field in Query belongs to which entity Parent or Details (i.e. I don't want a solution where I add conditions to check whether Dob exist in the Query or not)
Use case:
I'm using HotChocolate framework to integrate GraphQL which uses expression trees to build the queries. The issue I'm trying to solve is mentioned here
Your support and suggestions would be highly appreciated!

I managed to handle this issue by creating a View on the DB which joins both tables to act as single entity where I can filter, paginate and sort regardless whether it is one to one linked tables or it is single table.
Then did reverse engineering of that view using this link to be integrated with EntityFramework and finally managed to handle IQueryable on both entities.
In case of any other option available and suitable for HotChocolate, please add another answer to enhance my existing solution.

Related

Map column to child object in EF Core 3

Giving the sample below, is there any way to have Address in the same table as User without making use of table splitting or owned types (eg like EF6 complex types)? The generated SQL prevents me from using it and complex types does not seem to be supported in EF Core 3:
public class User
{
public int Id { get; set; }
public Address Address { get; set; }
public string UserName { get; set; }
}
public class Address
{
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
The only other options I see would be to map Address to its own table.
I will use a 1 to 0..1 relationship or include the properties in User directly.
Nevertheless, using Owned Types as a replacement for ComplexTypes like in EF 6 is horrible , if not completely useless from a SQL perspective, and I cannot see any reason for the joins. Maybe someone can clarify a proper justification for completness

EF foreign key reference using Id vs object

What is the difference between foreign key reference using Id vs object.
For example:
FK relation using Id
class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public int CategoryId { get; set; }
}
vs
FK relation using object
class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public Category Category { get; set; }
}
I have noticed from database that by using Id property the column essentially becomes non-null field.
Is that the only difference?
I think we can't query multiple tables at once i.e.querying related data?
When should I choose to use either options?
In your first example you're not adding a relationship, just an integer property named CategoryId.
In your second example, Entity Framework will create an integer column named "Category_ID", but you will be not be able to see this property in your model, so I like to explicitly add it my self and be able to use it along with the navigation property.
class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
[ForeignKey("Category")]
public int CategoryId { get; set; }
public Category Category{get;set;}
}
This way you can also control the data type of CategoryId, so you could make it optional (nullable)
public int? CategoryId { get; set; }
*The foreign key data annotation is not needed, unless you have property or navigation property names that do not follow the naming convention for foreign key property names (Bardr), it doesn't harm to explicitly declare it either for clarity purposes
This implies that you're creating a 1 to many relationship (1-*) with products and categories, so in your Category class you would be adding a collection navigation property for products
class Category
{
public int Id{ get; set;}
public string Name{ get; set; }
...
public ICollection<Product> Products{get; set;}
}
Basically it depends on your use case and what type of loading related data you choose. Whether you use Id or object reference or full relationship on both sides (Id and object) it depends on your overall application architecture. If you wil go and use full or object reference everywhere, you will (probably) end up with a mess, and you won't know whether you should query for some entities using their repository or if it'll be okay to include them to some other query. I highly recommend you to take a look at this book, especially chapter 19 (Aggregates) and 21 (Repositories). There you have an in-depth explanation of what I meant and much more. (This does not only apply to applications built in DDD way)

Clarification of one-to-many navigation properties in Entity Framework

I'm a bit confused by conflicting examples of one-to-many model relationships using EF that I'm seeing online.
One video I watched setup a relationship between tables like so:
public class CustomerType
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public int CustomerTypeId { get; set; }
public CustomerType CustomerType { get; set; }
}
So a Customer can only have one CustomerType, but a CustomerType can be used by many Customers. This code works fine, I can fetch a Customer's CustomerType with LINQ using Include.
Now I'm looking at another resource showing the same kind of relationship:
public partial class Standard
{
public int StandardId { get; set; }
public string StandardName { get; set; }
public virtual ICollection<Teacher> Teachers { get; set; }
}
public partial class Teacher
{
public int TeacherId { get; set; }
public string TeacherName { get; set; }
public Nullable<int> StandardId { get; set; }
public virtual Standard Standard { get; set; }
}
This looks almost the same, except:
In this example, the Standard class (equivalent to my CustomerType) has a navigation property back to a collection of Teachers, which my first example does not have. Is this just convenient to have if I want to get a list of all teachers for a given standard, or is it necessary to properly set up the relationship?
The properties in the second example are marked virtual and the first are not -- it seems that best practice is to make nav properties virtual, but is there a reason you wouldn't want to do that?
If it matters, I'm using MVC5 and EF6 and I just want to know if one example is right and one is wrong, or just two styles of getting to the same place.
Thanks!
The navigational properties are to make queries easier for the programmer. Your examples are basically the same with the difference that in Standard you can access Teachers through query while in CustomerType you can not access Customers with this CustomerType because you do not have it as a navigational property. Nevertheless, you can always include List<Customer> Customers in Customer Type.
Also it is better to add virtual to your navigational property for the sake of lazy loading.
MSDN
It depends on your needs, if you will never have to get the navigation property and just need a foreign key for sake of data integrity then you can simply add an integer and mark it as a foreign key. ex: instead of having a CustomerType instance, you can simply have a CustomerTypeId and that is it.
As for the virtual keyword, you can add it if you want to have a lazy loading enabled in your DBContext, cause EF generates proxy classes that inherits from your model classes and it overrides the virtual properties to add the needed logic to lazy load the navigation properties.
If you have a lazy loading disabled, then no need to mark any property as virtual

How to get parent entity property in child entity with foreign key relation in code first?

I have following two entities Doctor(parent) and DoctorPayment(child)
one possible way is to take Doctor object in DoctorPayment entity and get through Doctor.Name
But I only need DoctorName not whole object in DoctorPayment that should be mapped by DoctorId
I have mentioned just few properties of Doctor entity but it have around 50 properties so I don't want to take Doctor object in DoctorPayment
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public string Designation { get; set; }
public int ModifiedBy { get; set; }
}
public class DoctorPayment
{
public int Id { get; set; }
public int DoctorId { get; set; }
public decimal Amount { get; set; }
public DateTime Date { get; set; }
public int ModifiedBy { get; set; }
public Doctor Doctor { get; set; } // a possible way to take Doctor object
}
To be completely honest, my hunch is that you are probably prematurely optimizing. Unless you have already profiled your software and established that fetching just one instead of all columns is performance-critical, I would not bother to optimize it yet.
However, to answer your question: You can make EF retrieve single columns like this:
var name=dbContext.Doctors.Where(d=>d.ID==DoctorId).Select(d=>d.Name)
And of course you can also encapsulate this in a read-only property in the DoctorPayment class if you often need to access this.
Note that the disadvantage of this approach is that you are always fetching the Name from DB, even if the Doctor entity might already be prefetched through lazy loading by a previous query.
This is Currently not Possible with Entity Framework.EF does Support Object Mapping Only.You can't Map Single Column using EF.
Only Posssible way is to Get Maping for Whole object i.e Doctor and then you can use EF select to get Name only
i.e
var DoctorName=DoctorPayment.Doctor.Name
db.DoctorPayment.Include(x=>x.Doctor).Where(...).Select(x=>new{docName=x.Doctor.Name,.....})
it will generate a sql like
select doctor.name,.... from doctorpayment inner join doctor on ... where ...

Am I building the wrong entities in MVC?

Goal. I have a "Gift" entity that describes what someone has to offer (babysitting, dog walking, etc) with a rating. And I want a "GiftCategory" entity that gives general category descriptive information (pets, sports, automotive, etc) for someone to search apon and then get all gift that have those categories. A "Gift" entity can have multiple "GiftCategory" entities associated with it. I want the ability to search for a category and pull out all "Gift" entities that have been created with those categories associated with them. Here is what I have so far but it doesn't seem to work with the entity first approach. Maybe I need another table that connects the two entities because currently the way the two tables are connected doesn't seem correct?
Gift entity:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
Category entity:
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The "GiftCategory" table that gets created creates a gift_id column that links the "GiftCategory" back to a gift (not what I want)!!!!
It seems like I would need to create a entity that connects the two entities? Something like:
public class ConnectGifts
{
public int Id { get; set; }
public string GiftId{ get; set; }
public string GiftCategoryID{ get; set; }
}
This way I can have multiple categories for a Gift, but the thing I don't understand is with entity first I really don't need this entity I just need what would be this table to get/query the "GiftCategory" entities for ids then get the gift ids to get all the gifts. So it seems like creating this entity is overkill? Is there a way to do it without creating a third table/entity ("ConnectGifts") with code first? Or am I not understanding that all entities are tables and all tables are entities? I'm also using linq-to-sql for all querying.
You're looking for a many-to-many relationship and can be defined as:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Gift> Gifts { get; set; }
}
So each has a collection of the other. Gift has many Categories and Category had many Gifts. You could use a bridge table like you've done with ConnectGifts but it's not necessary with EF. Using just Gift and GiftCategory, EF will actually create the bridge table for you.

Categories

Resources