I have a student model with a departmentID foreign key. And the Department model has two property, ID and code. I cannot access the department code by the departmentID from student table. And yes I have this,
public virtual Department Department { get; set; }
in my student model. I tried this,
student.Department.code
but it returns null. I have no idea what I am missing. And I need the value to generate a student reg no. before saving student data. like this,
student.RegCode = student.ID + student.Department.Code;
first you had to call a variable to match the id and receive Department object
var code = db.Departments.Where(u => u.ID == student.DepartmentID).FirstOrDefault();
once you have your object data on a variable, you can access all its properties. like below,
student.RegCode = code.code+ "-" + student.ID;
Related
I'm new with Linq and hoping for some clarity on a particular query.
I have two tables (simplified for demonstration):
Table: Customer
CustomerId | Name
1 | John Smith
2 | Peter James
Table: Order
id | CustomerId | Total
1 | 1 | $100
2 | 1 | $200
Sample CustomerDto:
public class CustomerDto
{
public long CustomerId { get; set; }
public string Name{ get; set; }
public CustomerOrder[] CustomerOrderList{ get;set;}
}
Linq example for left outer join in the select here, they return string.empty if the join fails, I'm not sure the equivalent when I'm returning an object rather than a string.
My Linq query looks as follows. I've used the DefaultIfEmpty() to assist in a left outer join, however given I'm dealing with my object, I'm not sure how to return null if there isn't anything.
IQueryable<CustomerDto> search =
from customer in _database.Customer
join customerOrder in _database.CustomerOrder on customer.CustomerId equals customerOrder.CustomerId into CS
from subCustomerSale in CS.DefaultIfEmpty()
select new CustomerDto
{
CustomerId = customer.CustomerId,
Name = customer.Name,
CustomerOrderList = subCustomerSale
};
As I mentioned, I want to return a list of orders rather than one row per order. So there should be two records returned (the two customers), one with a list of orders and the other without any.
How do I achieve this?
The first step to make the entities easier to work with is to ensure that navigation properties are set up. If the table is called "Order" then the entity can be Order, or renamed to CustomerOrder if you like. A Customer entity can have an ICollection<Order> collection which EF can automatically map provided a consistent naming convention and normalization is used. (Otherwise explicit mapping can be provided)
For example:
public class Customer
{
[Key]
public int CustomerId { get; set; }
// other customer fields.
public virtual ICollection<Order> Orders { get; set; } = new List<Order>();
}
From here you are projecting Customers to a CustomerDTO, so we should also project the Orders to an OrderDTO. Note that when using navigation properties we don't have to explicitly join entities. We don't even have to eager load related data via Include(). The later would apply if/when we want to work with the entities rather than projections.
The resulting query would end up looking like:
IQueryable<CustomerDto> search = _database.Customer
.Select(c => new CustomerDto
{
CustomerId = c.CustomerId,
Name = c.Name,
Orders = c.Orders.Select(o => new OrderDto
{
OrderId = o.OrderId,
Total = o.Total
}).ToList()
});
The benefit is no need to explicitly write Join expressions. EF can help simplify accessing related data considerably rather than just facilitating using Linq as an alternative to SQL. This would return an empty list rather than #null if there are no Orders for that customer. It may be possible to substitute a #null if there aren't any orders, though worst case it could be post-processed after the results are materialized Ie:
var customers = await search.ToListAsync();
var noOrderCustomers = customers.Where(c => !c.Orders.Any()).ToList();
foreach(var customer in noOrderCustomers)
customer.Orders = null;
It really just boils down to whether the consumer is Ok knowing there is always an Orders collection that will be empty if there are no orders, or in the Orders collection is only present if there are orders. (via JSON etc. serialization)
The important details to consider: When filtering, such as filling in search criteria, do this before the Select as the IQueryable is working with entities so you have full access to the table fields. Adding Where clauses after the Select will limit the available fields to the ones you have selected for the DTO. (They will still bubble down into the SQL) There is a ToList inside the Select to build the Orders collection. This may look "bad" that it might be materializing data synchronously, but it will be executed only when the main query is. (Such as an awaited async operation on the IQueryable)
When projecting to DTOs be sure not to mix DTOs and entities such as:
IQueryable<CustomerDto> search = _database.Customer
.Select(c => new CustomerDto
{
CustomerId = c.CustomerId,
Name = c.Name,
Orders = c.Orders
});
... which can be tempting. The issue here is that "c.Orders" would return a collection of Order entities. Those Orders may have references to other entities or information you don't need to/want to expose to the consumer. Accessing references could result in lazy load costs, null references, or exceptions (i.e. disposed DbContext) depending on when/where they occur.
just put the ternary condition to achieve it like follows:
IQueryable<CustomerDto> search =
from customer in _database.Customer
join customerOrder in _database.CustomerOrder on customer.CustomerId equals customerOrder.CustomerId into CS
from subCustomerSale in CS.DefaultIfEmpty()
select new CustomerDto
{
CustomerId = customer.CustomerId,
Name = customer.Name,
CustomerOrderList = subCustomerSale == null ? null : subCustomerSale // add this line and you will get the null as well if there is no record
};
How to select records from db from a situation like below using eloquent
Tables:
Employee Table [ id,name]
Address Table [id,address_line1,employee_id,city_id]
City Table [id,name]
A Query like below does only return city id, but i need the city name as well
$employee = Employee::with('address')->get();
And My Employee Model have relationship as
public function address(){
$this->hasMany('address');
}
How to achieve the desired result so that the output of the query should give me city name from city table, based on the id from address table, without running new query for each city id to get names
I have two models User and Supplier. Both models have OneToMany polymorphic relations with Address model.
Tables:
suppliers
id - integer
name - string
users
id - integer
name - string
addresses
id - integer
is_primary - tinyint
addressable_id - integer
likeable_type - string
The primary address will be given and saved in addresses table when a new user created.
When modify an user, I want to get the primary address like all other data came from user table (I want to modify the primary address when modify the user) in the same form.
I want to access the address like: $user->address_line1; $user->zip; Is it possible? or how can i use the same form?
I have a similar setup on my application I have a getter for the primary address in the User model.
public function getPrimaryAddress()
{
return Address::firstOrNew([
'addressable_id' => $this->id,
'addressable_type' => User::class,
'is_primary' => true,
]);
}
I am trying to populate a JQGrid with LinQ but am having problems in getting a value from a foreign table.
Scenario: I have a Users table and a Country table. I am returning a List from the data layer and binding it to the grid. The values from the users table populate with no problem. My problem is when trying to link a JQGrid column to a column in the Country table, such as Country Name. If I debug the data returned from the data logic, the Country Name is filled in, but I can't find a way to link a JQGrid column to the Name column in the Country table. I tried, with no luck, the following:
<trirand:JQGridColumn DataField="Country.Name"/>
<trirand:JQGridColumn DataField="Country_Name"/>
Thanks for your time...
Have you tried using a ViewModel so it is not trying to bind to a navigation property?
something like:
public class UserViewModel
{
public int UserID { get; set; }
public string Username { get; set; }
public string CountryName { get; set; }
}
I have the following SQL query:
select
p1.[id],
p1.[useraccountid],
p1.[subject],
p1.[message],
p1.[views],
p1.[parentid],
max(
case
when p2.[created] is null then p1.[created]
else p2.[created]
end
) as LastUpdate
from forumposts p1
left join
(
select
id, parentid, created
from
forumposts
) p2 on p2.parentid = p1.id
where
p1.[parentid] is null
group by
p1.[id],
p1.[useraccountid],
p1.[subject],
p1.[message],
p1.[views],
p1.[parentid]
order by LastUpdate desc
Using the following class:
public class ForumPost : PersistedObject
{
public int Views { get; set; }
public string Message { get; set; }
public string Subject { get; set; }
public ForumPost Parent { get; set; }
public UserAccount UserAccount { get; set; }
public IList<ForumPost> Replies { get; set; }
}
How would I replicate such a query in LINQ? I've tried several variations, but I seem unable to get the correct join syntax. Is this simply a case of a query that is too complicated for LINQ? Can it be done using nested queries some how?
The purpose of the query is to find the most recently updated posts i.e. replying to a post would bump it to the top of the list. Replies are defined by the ParentID column, which is self-referencing.
The syntaxt of left join in LINQ is :
(i put it in VB.NET) :
Dim query = From table1 in myTable.AsEnumarable 'Can be a collection of your object
Group join table2 in MyOtherTable.AsEnumerable
On table1.Field(Of Type)("myfield") Equals table2.Field(Of Type)("myfield")
In temp
From table2 in temp.DefaultIsEmpty()
Where table1.Field(Of Type)("Myanotherfield") is Nothing 'exemple
Select New With { .firstField = table1.Field(Of Type)("Myanotherfield")
.secondField = table2.Field(Of Type)("Myanotherfield2")}
Something like that
Ju
I discovered that NHibernate LINQ support doesn't include joins. That, coupled with an apparent inexperience with complex LINQ queries, I resorted to the following work around:
Add a Modified column to the posts table.
On reply, update parent's Modified column to match reply's Created column
Sort by and retrieve the value of the Modified column for post display.
I think it's a pretty clean work around, given the limitations of the code. I dreadfully wanted to avoid having to resort to adding another entity, referencing a view, or using a stored procedure + data table combination for this particular piece of code only. Wanted to keep everything within the entities and use NHibernate only, and this fix allows that to happen with minimal code smell.
Leaving this here to mark as answer later.