Adding a custom member to a mapped type - linq

I'm using Linq 2 Sql and I'd like to add a custom member on one of my data type. For example: I have tables Companies, Departments and Employees. Departments has a FK in Companies and Employess has a FK in Deparments. Very simple.
My goal is to add an EmployeeCount property on Company that will, of course, returns the number of employee in the company (by suming the number of employee in company's departments).
As you may know, it's really trivial to do: just add a member on the partial class and do the stuff. The problem is, I now want to sort on this custom member.
How can I write this custom member for Linq to be able to translate the logic into a valid SQL orderby? I tried with a SPROC but did not success.
Any help appreciated!
Fabian

I guess your may need to add this column to your schema, in order for SQL server to recognize it and take in under consideration in his optimizations.
I would have add a trigger that will update this column automaticly upon changes on your data.

Related

Should I create three models or a polymorphic type

I have a Laravel 8 application and am wondering how to solve the problem of how to solve a typical polymorphic issue. I have an Employee model. That Employee can be an ExecutiveEmployee or EntryLevelEmployee. There will be methods an ExecutiveEmployee has that an EntryLevelEmployee doesn't have and the inverse is also true.
Using Laravel 8, is it right to create a base Employee model (without a corresponding table?) and then create two models named ExecutiveEmployee and EntryLevelEmployee that inherit from Employee? This would also imply that both employee types will have two different database tables, even though there will be a lot of overlapping data.
Does it make sense to just have one Employee model and create a migration that has the employee type listed in the model? I am assuming that it's ok if an EntryLevelEmployee has some database attributes which are relevant to it that may or may not be relevant to an ExecutiveEmployee type here, or is that an incorrect assumption?
What's the correct way to model this in Laravel 8? I prefer to keep everything in one table because of how similar the models are. I do have to keep in mind that there will be data that one has that the other doesn't. There will be different accessor methods as well.
Is it possible to have everything in one employees table while utilizing multiple models? Meaning, if I create two models named ExecutiveEmployee and EntryLevelEmployee they would both query the underlying table employees?
UPDATE 1
The more I research, the more I think polymorphism is the incorrect approach here and what I might need is Single-Table Inheritance. This package seems to bring the capability to Eloquent. Would there be a good reason to not use this?
I would use polymorphic relationships in this case, because you are more flexible and have less coupling.
Using the Single Table Inheritance (STI), you can add type specific columns in the employees table and make them nullable. But think about adding/removing types in the future.
executive_employees
id - integer
executive_specific - string
entry_level_employees
id - integer
entry_level_specific - string
employees
id - integer
name - string
email - string
employable_id - integer
employable_type - string
As for the STI the same would be
employees
id - integer
name - string
email - string
type - string
executive_specific - nullable string
entry_level_specific - nullable string
So STI would be suitable when you don't have type specific columns. But you want to add specific behavior in your code. For example a User type (Admin, Author).
Even so, it's a matter of preferences.
It really depends on the state and behavior of your employee object.
Below are few points I will consider to make a decision
If your objects' states/properties are different then definitely you will create different models as your data will be stored in different tables.
If most states/properties are same and some are different, you can
consider storing all in one table/model and for the difference in
behavior create separate table like Ron Van Der Heijden has
suggested and you can consider query scope with that to make
transaction with database.
And another view will be
How many JOINs you will create if you will create different tables,
will that impact the performance and other stuffs, will it make your
code complex?
Can you make simpler relations and handle stuffs independently?
When you are making an API, will your
code make the api overworking? or you need to create too many request
for any operation?
These stuffs will decide how you will make a decision.
Update 1:
Another point I would like to add about the package you are thinking to use, consider using a parent key in table and you can define relationships in a single model.I do not think you need to use a package, you can define it yourself, I guess.
I don't understand why you don't create a simple one-to-many relation. Based on the information you provided, the polymorphic relation looks unnecessary. I think the right way is to create employee_roles table and relations. Then you can give different permissions to different employee types. There are several ways to do that. You can create a middleware to create route restrictions. You can check the role before executing a function in the controller, and run only if the employee has permission. You can use if-else in blade not to render the parts that can't be used by auth user etc.
If you have different “types” of employees, and each employee type should have different logic then yeah, that sounds like a polymorphic relationship.

Oracle ADF many-to-many with additional attribute

I'm developing a ADF Fusion Web Application and have some problems with EntityAssociations and ViewLinks.
I have a database table Project with id, name etc. Also I have a table Technology which only contains a id and the name of the technology, for example "ADF".
The relationship between theese two entities is many-to-many. Means one project can have multiple technologies assigned and inverse a technology can be assigned to multiple projects.
This relationship is described trough a join table named Project_Technology. Columns of this table are Project_FK, Technology_FK and Effort. Project_FK and Technology_FK are a composite primary key, Effort is an additional attribute.
Can someone explain me how to map EntityObject and ViewObjects that I can access the Effort, too? "Regular" many-to-many associations aren't that hard to implement but I am really struggling with the additional attribute.
Any help is appreciated. Thanks in advance!
Edit:
I could solve my issues. See answer below for details.
I got it working.
The Problem was the composite primary key on my join tables. It seems like ADF doesn't like them. I put a extra column ID on the join tables and now I can insert values by using the CreateInsert Data Controls.

Runtime join in lightswitch

I have a generic group members table with a GUID for a "group type" and a GUID for "referenced object". An example would be if I have a table of customers(each having a GUID) I can group them under "already paid" by creating a group GUID and in my "Group members table" referencing every customer by their respective GUID. This allows for any type of group to be added to the model as we expand(without adding extra tables).
Here is the problem. I have created a subquery in an entity in order to filter the universal group members table for a certain group and what "items" are and are not in that group; like so:
partial void ElementsNotMemberOfGroup_PreprocessQuery(int? UniversalGroupTypeIDParameter, int? UniversalGroupsIDParameter, ref IQueryable<UniversalGroupMember> query)
{
query = query.Where(x => x.UniversalGroup.UniversalGroupType.UniversalGroupTypeID == UniversalGroupTypeIDParameter);
query = query.Where(x => x.UniversalGroup.UniversalGroupsID != UniversalGroupsIDParameter);
}
This returns the GUIDs for the referenced object in the group, but for a user that's useless. I need to join this table and my customers table at runtime on the GUID so I can extract the customer info and display it.
Any Ideas?
LightSwitch wasn't really created with this kind of scenario in mind. LightSwitch makes things very easy for you when you create relationships between tables that are, well, "related". When you do this, you never need manual joins between entities.
While it's possible to do something similar to what you're describing (see the link below), it's a lot more work to achieve it, and in my opinion it isn't really worth the extra trouble. Not only that, but as you're discovering, it complicates even the most simple operations.
In essence, you're working against LightSwitch, instead of with it. My advice to you would be that if you really must do this type of manual optimization, then LightSwitch may not be the best product for you to use.
Beth Massi has a blog article, Using Different Edit Screens Based on Record Types (Table Inheritance), which isn't exactly what you're doing, but it may give you some ideas if you decide to still use LightSwitch for your project.

Linq doubts with DB context

Hi I have a question that is braking my mind for some days.
I have my SQL server Database and my C# application.
In the DB I have differemt tables, let me show you a simple ex
Tables:
Person
Relationship
City
Business Rules:
The person are from a City, so the person has IdCity
A person has a relationship with other person, and about that relationship you need to save the starting date.
In other projects I already did something like that, but in this proyect this is not working for me.
When I retrieved with LinQ the information about the person, the city is not coming, and an error appears when I try "person.city.description", for ex.
I try using Include("City") in the linq query, but it didn't work. Besides that, I don't know how to manage the circular reference to the person to person relationship.
One important thing, that I think that can be the problem, is that I rename all the tables from the DataModel, for example, the table in database is called Prd_City, so I change the Name and the Entity Set Name for City in c# project. So in the included I have to use the real table name, in other case the query fail, but if I use the real name nothing happens.
using (var context = new MyContext())
{
List<Person> oPeople = (from p in context.Person.Include("Prd_City")
select p).ToList();
return oPeople ;
}
Any help will be welcome.
Thanks!
"It didn't work" is never a good description of your problem. But from the rest of your question I can infer that Person has a navigation property named "Prd_City", while you expected it to be "City". The thing is: you renamed the entities, but not the navigation properties in the entities.
My advice (for what it's worth): it seems that your work database-first. If you can, change to code-first and manually map the POCO classes to their table names, and properties to their database columns. It may be a considerable amount of work (depending on the size of your data model), but after that you will never run the risk of EF "un-renaming" your entities. Besides, the DbContext API is easier to use than ObjectContext. Currently, it's the preferred EF API.

Very slow search of a simple entity relationship

We use CRM 4.0 at our institution and have no plans to upgrade presently as we've spend the last year and a half customising and extending the CRM to work with our processes.
A tiny part of model is a simply hierarchy, we have a group of learning rooms that has a one-to-many relationship with another entity that describes the courses available for that learning room.
Another entity has a list of all potential and enrolled students who have expressed an interest in whichever course.
That bit's all straightforward and works pretty well and is modelled into 3 custom entities.
Now, we've got an Admin application that reads the rooms and then wants to show the courses for that room, but only where there are enrolled students.
In SQL this is simplified to:
SELECT DISTINCT r.CourseName, r.OtherInformation
FROM Rooms r
INNER JOIN Students S
ON S.CourseId = r.CourseId
WHERE r.RoomId = #RoomId
And this indeed is very close to the eventual SQL that CRM generates.
We use a Crm QueryEntity, a Filter and a LinkEntity to represent this same structure.
The problem now is that the CRM normalizes the a customize entity into a Base Table which has the standard CRM entity data that all share, and then an ExtensionBase Table which has our customisations. To Give a flattened access to this, it creates a view that merges both tables.
This view is what is used by the Generated SQL.
Now the base tables have indices but the view doesn't.
The problem we have is that all we want to do is return Courses where the inner join is satisfied, it's enough to prove there are entries and CRM makes it SELECT DISTINCT, so we only get one item back for Room.
At first this worked perfectly well, but now we have thousands of queries, it takes well over 30 seconds and of course causes a timeout in anything but SMS.
I'm given to believe that we can create and alter indices on tables in CRM and that's not considered to be an unsupported modification; but what about Views ?
I know that if we alter an entity then its views are recreated, which would of course make us redo our indices when this happens.
Is there any way to hint to CRM4.0 that we want a specific index in place ?
Another source recommends that where you get problems like this, then it's best to bring data closer together, but this isn't something I'd feel comfortable in trying to engineer into our solution.
I had considered putting a new entity in that only has RoomId, CourseId and Enrolment Count in to it, but that smacks of being incredibly hacky too; After all, an index would resolve the need to duplicate this data and have some kind of trigger that updates the data after every student operation.
Lastly, whilst I know we're stuck on CRM4 at the moment, is this the kind of thing that we could expect to have resolved in CRM2011 ? It would certainly add more weight to the upgrading this 5 year old product argument.
Since views are "dynamic" (conceptually, their contents are generated on-the-fly from the base tables every time they are used), they typically can't be indexed. However, SQL Server does support something called an "indexed view". You need to create a unique clustered index on the view, and the query analyzer should be able to use it to speed up your join.
Someone asked a similar question here and I see no conclusive answer. The cited concerns from Microsoft are Referential Integrity (a non-issue here) and Upgrade complications. You mention the unsupported option of adding the view and managing it over upgrades and entity changes. That is an option, as unsupported and hackish as it is, it should work.
FetchXml does have aggregation but the query execution plans still uses the views: here is the SQL generated from a simple select count from incident:
'select
top 5000 COUNT(*) as "rowcount"
, MAX("__AggLimitExceededFlag__") as "__AggregateLimitExceeded__" from (select top 50001 case when ROW_NUMBER() over(order by (SELECT 1)) > 50000 then 1 else 0 end as "__AggLimitExceededFlag__" from Incident as "incident0" ...
I dont see a supported solution for your problem.
If you are building an outside admin app and you are hosting CRM 4 on-premise you could go directly to the database for your query bypassing the CRM API. Not supported but would allow you to solve the problem.
I'm going to add this as a potential answer although I don't believe its a sustainable or indeed valid long-term solution.
After analysing the indexes that CRM had defined automatically, I realised that selecting more information in my query would be enough to fulfil the column requirements of an Index and now the query runs in less then a second.

Resources