views:

1242

answers:

1

I've got a table "Expenses" that contains an FK value to an "ExpenseType" table. Right now, if I want to save a new expense, I first get the int value of the FK, do a lookup to the ExpenseType table, and assign the object to the expense object. For example:

//create new expense
var e = new Expense();

//lookup the associated expense type
var et = context.ExpenseTypeSet.First(e -> e.expenseTypeID == 10);

//set field values
e.expenseName = "Some name";
e.expenseType = et;

//save
context.Save();

Is there a way to create/insert a record without first being forced to do a lookup against the FK table? The lookup is not needed and forces extra database hits. I already know the FK ID... so is there a way to just set the ID and allow it to be happy?

Thanks in advance -

+4  A: 

You can do this using the EntityReference too:

e.expenseTypeReference.EntityKey 
   = new EntityKey("MyContainer.expenseTypeSet", "expenseTypeID", 10);

I have a tips series that covers this and related issues:

The one you might want to look at in particular is this Tip 7 which talks about creating fake properties for FKs. You don't need to go that far, unless you want to, but the principles are useful.

Alex James
Isn't this kind of against the concept of the entity framework? I've run into this before myself, but by setting the ID of something directly kind of breaks the object representation of a database value. This is like mixing the two. I suppose there's no law against it, but just seems like the idea is lost. More of a silly philosophical thing.
Programmin Tool
Oh man, this is the best thing since peanut butter! Ok, so question - what does MyContainer refer to?
Chu
@Programming Tool - I have ran into people that like both ways. Some, like you, believe this is breaking all sorts of rules; others feel that it's a sin to have to do a db lookup for each FK just to do an insert.In my case, if I were to supply a non-existant ID, the db wouldn't allow it because of constraints that are built into it.
Chu
Chu you can get the real "MyContainer" by calling ctx.DefaultContainerName
Alex James
@Programming Tool - There are strong arguments each way. The problem with hiding the FK completely is that while from an OO perspective this is the right thing to do, most surrounding .NET infrastructure expects to be able to set an FK directly. For example standard databinding and even MVC binders. So while not pure it makes things a lot simplier when write code on the Microsoft Stack.
Alex James
How would this differ if my table had a composit key of 2 or more fields?
Chu
Where there are advantages, OO principals should be applied. But when dealing with relational system some OO principals will become outright idiotic... making a DB select just to set an FK value is a classic example of moronic OO principals being applied where it doesn't make practical sense or offer any practical advantage.There will always be impedance mismatch between relational and object worlds. Near the boundary you have to start violating principals to find a middle ground. The whole Entity Key thing is a tool that lets you restore common sense to this kind of problem case.
Stephen M. Redd
I keep getting this exception: "The member with identity 'tbl_Task' does not exist in the metadata collection"In the data model, the name of the item that shows up with the association for the Expense entity is "tbl_Task" - The actual name of the entity used for retrieving tasks is "Task" and "TaskSet" - so which name does it really want here? I have tried all combinations with no luck (even mixed the cases).
Chu
I wouldn't exactly call it "moronic" if I'm using the same context as the actual hit to retrieve the object and fill is most likely negligible. (Provided the servers aren't some crazy distance apart) Unless I'm completely wrong, it shouldn't be reopening a connection at that point, just using the same one. There is also a chance the requested item is already in the context so in reality I can't see this being a huge problem. I will admit hitting the database twice instead of just chucking the number in could seem silly, but in the scheme of things keeps a semblance of consistency.
Programmin Tool
Sorry, turning this into some kind of internet argument silliness like Parametrized SQL vs Stored Procedures. Just not sure words like "moronic" are really needed here.
Programmin Tool
I don't mean "moronic" to be offensive towards people, just descriptive of the OO technique when mis-applied. That second select seems mildly inconvenient on the surface, but once you start getting into iterative scenarios the OO adherent technique becomes a real problem. Imagine the scenario in a loop... say a 100,000 or million records? The OO technique wouldl issue an additional sub-query for each iteration, which is what I call "moronic". The framework gives you a practical alternative so you aren't stuck blindly adhering to a bad idea just because it fits academic OO ideals.
Stephen M. Redd
I would think that in a loop, after say X number of iterations, all possible reference items would be loaded into the context, therefore no longer needing to retrieve anything from the database. Now in your scenario if there are say 10000 reference items, then yes that could get a little silly. However, if the table itself has very few rows (100 or less), the initial grab for say type of id 1 will eliminate the sub query for every iteration that needs type of id 1. Now if it didn't save the object in the context on the first grab, then yes it would constantly be hitting the database.
Programmin Tool
The framework may be able to load and re-use the related references, but that really depends how you specifically implement your code more than anything. If you can, the best bet is to load the related table and just write using the OO techniques. Efficiency nuts will still prefer the more direct write via the Entity Key though and in some cases you may have no practical choice about it.
Stephen M. Redd
I thought I would throw into the fray. Practically speaking you shouldn't have to query first before you update. Particularly when you are dong ASP because of the Rest style of the web. This is esp. the case when using the MVC which part of the goal is Restful.
DrydenMaker