linq2sql, one to many through relations - linq-to-sql

I have
OrgUnits,
OrgUnitJobs,
Employees,
OrgUnitJobEmployee (this one may seem redundant in this context, its here fyi)
tables.
org units have jobs defined in OrgUnitJobs (1..n)
employee (can also have many jobs) has jobs defined in OrgUnitJobEmployee table.
and employee has a PrimaryJob (1..1) in OrgUnitJobs table, so how do I get a list of all the employees who's primary job is in that org unit.
I am using LINQ2SQL ORM, so I have an OrgUnit partial class, I would like to be able to get this employee list within that partial ORM class, without writing another query, or a linq select.
I just dont want to go to my OCRepository class and write a GetEmployeeListForOrgUnit(orgUnitId) there, it does not sound right.

Check DataContext.LoadOptions to tweak what's included in the first query. This means it'll execute a join, instead of N subqueries.
In your case, something like:
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Job>(j => j.PrimaryEmployees);
dbContext.LoadOptions = dlo;

Related

Possible to reference another table as a row in a table?

I have a Table called Payments, and a couple others called Invoices, Subs, Licenses.
Is it possible to add a reference to these tables in Payments? Something that would generate this
result => CREATE TABLE Payments (
Invoices table,
Subs table
)
I'm thinking in the same way I can put an object into an array in other languages.
EDIT: Im using MySQL. Basically, I want to map them to Java with one class called Payments and was wondering if I could do this on the db serverside. Otherwise I would have to figure out how to map all of them in the Javaclass. Which Im thinking now might be easier
In MySQL, you can have a subquery virtually anywhere you can use an expression. But it must return a single value.
You can use a "derived table", which is a subquery, as a table-like thing after FROM or JOIN.
What you typed may be better handled with a VIEW:
CREATE VIEW Results AS
SELECT i.*, s.*
FROM Invoices AS i
JOIN Subs AS s ON i.foo = s.foo
(where foo is the column used for relating those two tables together.)

Changing a complex join into a Sequel association

Right now I have a relatively complex piece of code (it's not that complex) that I'd like to simplify through Sequel associations
MyApp::Model::Node.where { last_heartbeat > Time.now - HEARTBEAT_TIMEOUT.seconds }.join(:system_status, node_id: Sequel.expr(:node__id))
Pretty nasty, this statement.
So I'd like to accomplish one thing, pretty much: simplify the above statement by replacing the join with an association in my SystemStatus Model.
Let me explain the above join:
I have two tables Node and SystemStatus. The comparison last_heartbeat > Time.now - HEARTBEAT_TIMEOUT.seconds essentially gives me all the "live nodes" in my application (my application is clustered, meaning the user can spawn multiple instances of it at the same time).
So that mess of a statement gives me "all the statuses of my live nodes" which is joined by system_status.node_id to node.id.
So I started this out by establishing my one to one relation in SystemStatus - this sets the association to the node table
one_to_one :node
Next, I needed to join it by a specific key node.id because it's not a straightforward join
one_to_one :node, key: :id
But my question is:
How do I do the rest of this association
Should I perform the association in Node as opposed to SystemStatus? It seems I could simply do one_to_one :system_status and not have to specify a key.. The above complex join resides in the node Model anyways.
If you have the association in SystemStatus, you need to use many_to_one, as the foreign key is in the that model's table, not the associated model's table. You can just transfer your where condition to the association using a block:
SystemStatus.many_to_one :live_node, class: :Node, key: :node_id do |ds|
ds.where{last_heartbeat > Time.now - HEARTBEAT_TIMEOUT.seconds}
end

LINQ Select Many question

Can you use SelectMany in a query against your DB and if you can, what type does the column need to be in order to do this? I am messing around with LINQPad and anytime I try to use SelectMany I get an error, and from what I am reading it sounds like the type in your lambda expression has to be a collection.
Houses.SelectMany(h => h.HousesPersons.Select(hp => hp.Person.Name))
If you have 3 Tables. Houses, HousesPersons and Persons.
Houses has a One->Many relationship with Persons using HousesPersons to store HouseId and PersonId.
This query will get you a list of all persons in all houses in a flat list, rather than grouped by House.
EDIT: Sorry I can't get AdventureWorks to work on my machine to use a text book example.
SelectMany projects each element of a sequence (i.e. a property of an object that is an enumeration or list) into an IEnumerable<T> and flattens the resulting sequence of sequences into a single sequence / IEnumerable<T>.
Having said that it could be applicable in i.e. a Linq to Entities environment - you could i.e. select select the navigation properties (related entities) of multiple entities and spit them out in a single list.

What constitutes explicit creation of entities in LINQ to SQL? What elegant "solutions" are there to this limitation?

I've been having problems with the rather famous "Explicit construction of entity type '##' in query is not allowed." error.
Now, for what I understand, this exists because if explicit construction of these objects were allowed, tracking changes to the database would be very complicated.
So I ask: What constitutes the explicit creation of these objects? In other terms:
Why can I do this:
Product foo = new Product();
foo.productName = "Something";
But can't do this:
var bar = (from item in myDataContext.Products
select new Product {
productName = item.productName
}).ToList();
I think that when running the LINQ query, some kind of association is made between the objects selected and the table rows retrieved (and this is why newing a Product in the first snippet of code is no problem at all, because no associations were made). I, however, would like to understand this a little more in depth (and this is my first question to you, that is: what is the difference from one snippet of code to another).
Now, I've heard of a few ways to attack this problem:
1) The creation of a class that inherits the linq class (or one that has the same properties)
2) Selecting anonymous objects
And this leads me to my second question:
If you chose one of the the two approaches above, which one did you choose and why? What other problems did your approach introduce? Are there any other approaches?

Linq to SQL and Gridview Datasource

I have a question related to this one. I don't want to do a calculation (aggregation), but I need to get display values from an association. In my C# code, I can directly reference the value, because the foreign key constraint made Linq generate all the necessary wiring.
When I specify the IQueryable as the Gridview datasource property, and reference something that is not a column of the primary entity in the result set, I get an error that the column does not exist.
As a newbie to Linq, I am guessing the assignment implicitely converts the IQueryable to a list, and the associations are lost.
My question is, what is a good way to do this?
I assume that I can work around this by writing a parallel query returning an anonymous type that contains all the columns that I need for the gridview. It seems that by doing that I would hold data in memory redundantly that I already have. Can I query the in-memory data structures on the fly when assigning the data source? Or is there a more direct solution?
The gridview is supposed to display the physician's medical group associations, and the name of the association is in a lookup table.
IQueryable<Physician> ph =
from phys in db.Physicians
//from name in phys.PhysicianNames.DefaultIfEmpty()
//from lic in phys.PhysicianLicenseNums.DefaultIfEmpty()
//from addr in phys.PhysicianAddresses.DefaultIfEmpty()
//from npi in phys.PhysicianNPIs.DefaultIfEmpty()
//from assoc in phys.PhysicianMedGroups.DefaultIfEmpty()
where phys.BQID == bqid
select phys;
(source: heeroz.com)
So, based on Denis' answer, I removed all the unneeded stuff from my query. I figured that I may not be asking the right question to begin with.
Anyways, the page shows a physician's data. I want to display all medical group affiliations in a grid (and let the user insert, edit, and update affiliations). I now realize that I don't need to explicitly join in these other tables - Linq does that for me. I can access the license number, which is in a separate table, by referencing it through the chain of child associations.
I cannot reference the medical group name in the gridview, which brings me back to my question:
AffiliationGrid.DataSource = ph.First().PhysicianMedGroups;
This does not work, because med_group_print_name is not accessible for the GridView:
A field or property with the name 'med_group_print_name' was not found on the
selected data source.
Again, bear with me, if it is all too obvious that I don't understand Linq ... because I don't.
Your query seems strange. You should try to simply display
ph = from phys in db.Physicians
where phys.BQID == bqid
select phys;
in your grid. That should work.
Also, why the calls to Load()? If the DataContext is not disposed when the grid is binding, you should not need it.
If you still have issues, can you please post the error message you get, that would help...
Part 2
The problem is that you have the name is effectively not in the PhysMedGroup. You need to navigate one level down to the MedGroupLookup to access the name, since it is a property of that class.
Depending on the technology you are using (it seems to be either WinForms or Web Forms), you will need to configure your data-binding to access MedGroupLookup.med_group_print_name.