Cascading deletes on *Derived Entities* - c#

OK, check out the following simple object model:
Entity ConcreteThingy derives from AbstractThingy.
Entity Owner can have at most 1 ConcreteThingy.
No two Owners can have the same ConcreteThingy.
EDMX:
DB model (TPT):
What I want:
I want 2 things, in descending order of priority:
Thing I want #1: Above all, I want the simplest, most concise, cleaner solution to #2
below.
Thing I want #2: When I delete an Owner, I want to automatically delete any potentially associated ConcreteThingy, along with the base AbstractThingy.
What I'm doing:
So, naturally, I went to the EDMX and simply turned on Cascade delete on the Owner 0 ↔ 0..1 ConcreteThingy association.
This works well in setting the Delete rule of the FK_ConcreteThingy_Owner relationship to Cascade, but I don't see ANY constraints/DB code that makes sure that the AbstractThingy record gets deleted as well.
Again, when I delete an Owner, the corresponding ConcreteThingy (if any) is deleted, but it leaves the dangling AbstractThingy, which not surprisingly, I don't want.
Can somebody please tell me what is the standard way to implement this type of tasks using EF 5?
I've tried by making AbstractThingy abstract, hoping that the SQL code would somehow infer what I want (understandably there would be some sort of chicken-and-egg conundrum for the generator, but hey, at least I tried it.)
Or should I define some sort of smart-ass referential constraint in my EDMX?
Or is it expected that I'd go to the DB and write code myself, like a trigger, etc...!?!? That would be a bit of a[nother] fiasco for EF and its design tools.
Thanks.

Related

Database First Entity Framework multiplicity

I am working on a simple database and to be specific here is the model generated by database first approach (Visual Studio 2017 Community, Entity Framework 6.2):
Generated Database Model
I'd like the UserMessage table to be able to point to itself with a field named AnswerId, this is a nullable foreign key referencing its primary key. Again, to be specific, here is the part where I create the table:
UserMessage table script
My problem is that when Entity Framework generates the classes based on the existing database everything goes fine except for this particular table, in which EF suggests (I don't know why) that the UserMessage table has a multiplicity of 0..1 - * to itself while it should 1 - 0..1 (because a message may have a direct answer, but not more than 1, though that message, which is the answer, could also have an answer, so it's just like a linked list).
Here is the generated class: UserMessage generated class
To sum up the whole thing: I'd like to know why Entity Framework generates my class the way it does, and how could I make it generate it so that I only have a virtual property pointing to the answer (in case it has one), but not a collection.
Thank you for your answers!
I think what you're seeing is a correct interpretation by EntityFramework.
UserMessage1 represents a collection of all the UserMessages that have references to the parent as their answer. I understand that you probably won't use that collection for anything but it's not wrong that it's there. UserMessage2 seems to be the property you're looking for. Maybe you could rename those properties in the diagram so they're not confusing.
UserMessages1 = MessagesThatReferenceMe
UserMessages2 = the Message that I may or may not reference
I don't see how you can stop EF from generating this collection. I think if you delete the property in the diagram you will have to delete it every time you update the diagram.
Maybe try deleting the 2nd UserMessage navigation property in your model.

Entity Framework "detach without deletion" for filtering

I'm having a problem with Entity Framework and filtering architecture.
Let's say that I have a couple of related entities, and I want to do some changes to them, based on a filter.
So, for example I have Orders and Orderlines (to put a simple example)
I have order1, with orderline1, orderline2, orderline3 relationships in the DB
Then I receive an update request for order1 but only for orderline1 and orderline3
I get the data from the db using entity framework, which retrieves an objectgraph of the order and its lines.
Is there a way to filter these entity objects so that I can work with an objectgraph that contains order1 and orderline1 and orderline3, but NOT orderline2 without that being a problem later?
Because if i remove orderline2 from the entitycollection, i get later on concurrency errors (or deleted entities, which is something i don't want)
I hope the question is clear, I know that there could be other ways (iterating and not performing updates on orderline2, so it remains the same and no changes are made) but the way the architecture was made doesn't let me do that right now.
If I could say "don't track any more changes to orderline2, just ignore any changes that I do to this particular object and descendants, just leave it in the DB the way it is", so that I can just remove it from the collection and move forward, that'd be perfect
Thanks!
You can go multiple ways as you already described yourself as well:
Iterating through all orderlines and only modifying those that need to be modified (but that isn't an option as you stated)
The alternative you described to specifically not track changes for orderline2 is not possible in a "normal" EF situation where the ObjectStateManager is responsible for change tracking (as far as I know). In a scenario with Self Tracking Entities it's more easy because every STE has it's own unique ChangeTracker on board which can be easily switched off.
But the most easy option would be to exclude the orderlines you dont want to modify in the "select" statement or the retrieval of the entities. Something like:
private void ModifyOrderLines(int orderID, List<int> orderlineIds)
{
using(Context context = new Context)
{
List<OrderLines> orderlines =
context.OrderLines.
Where(orderLine => orderLine.OrderID == orderID && orderlineIDS.Contains(orderLine.ID))
}
}
Assuming you have set up clean foreign key relationships which were translated into Navigation Properties in EF. So what you do is to get a list of OrderLines which belong to a certain order and have an ID that's in your list of OrderLines that need to be modified.
Afterwards you change the orderlines and apply the changes to the context and call SaveChanges. This is just a basic way of how you could do things. I don't know your exact setup but I hope this helps.
EDIT
Based on your comment I should just go for the easy way and write a loop as you already proposed. Why not? I don't think there are many alternatives, and if there are then they would make things overcomplicated.
So something like this might just work:
ObjectContext.OrderLines.ForEach(o => if(orderlineIds.Contains(o.ID) {o.SomeProperty = SomeValue}));
Or you could just write the loop yourself.
EDIT2
You already mentioned detaching from the ObjectContext in the title of your post. Why don't go that way then? You tell that you have no control over the ObjectContext that you get, that it is passed into several methods and that you get update requests for certain entities. Then detaching those entities that are not needed for the update request can be an option too. Maybe this topic on MSDN might help you decide. Afterwards you might attach the detached objects again for they maybe needed for subsequent "client" calls. But this depends on how you manage the ObjectContext.
Do you keep the ObjectContext "alive" over multiple "client" calls or do you instantiate it over and over again for specific client calls. I do not get the situation totally clear...

DefiningQuery and no <DeleteFunction> element exists in the <ModificationFunctionMapping> element to support the current operation

Unable to update the EntitySet 'InstanceObjectName' because it has a DefiningQuery and no element exists in the element to support the current operation
Make sure that your table has a primarykey!
the Entity Framework doesn't know whether a given view is updatable or not, so it adds the element in order to safegaurd against having the framework attempt to generate queries against a non-updatable view.
If your view is updatable you can simply remove the element from the EntitySet definition for your view inside of the StorageModel section of your .edmx, and the normal update processing will work as with any other table.
If your view is not updatable, you will have to provide the update logic yourself through a "Modification Function Mapping". The Modification Function Mapping calls a function defined in the StorageModel section of your .edmx. That Function may contain the name and arguments to a stored procedure in your database, or you can us a "defining command" in order to write the insert, update, or delete statement directly in the function definition within the StorageModel section of your .edmx.
Of the two options, if your view is updatable (which it sounds like it may be) the easiest is certainly to remove the inserted by the designer.
UPDATE: I've gotten a few upvotes on this lately, so I figured I'd let people know the advice I give below isn't the best. Since I originally started mucking about with doing Entity Framework on old keyless databases, I've come to realize that the best thing you can do BY FAR is do it by reverse code-first. There are a few good articles out there on how to do this. Just follow them, and then when you want to add a key to it, use data annotations to "fake" the key.
For instance, let's say I know my table Orders, while it doesn't have a primary key, is assured to only ever have one order number per customer. Since those are the first two columns on the table, I'd set up the code first classes to look like this:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
By doing this, you've basically faked EF into believing that there's a clustered key composed of OrderNumber and Customer. This will allow you to do inserts, updates, etc on your keyless table.
If you're not too familiar with doing reverse Code First, go and find a good tutorial on Entity Framework Code First. Then once your'e comfortable with this, go find one on Reverse Code First (which is doing Code First with an existing database). Then just come back here and look at my key advice again. :)
Original Answer:
First: as others have said, the best option is to add a primary key to the table. Full stop. If you can do this, read no further.
But if you can't, or just hate yourself, there's a way to do it without the primary key. Basically, what we're going to do is lie to the Entity Framework and tell it there's a primary key.
In my case, I was working with a legacy system (originally flat files on a AS400 ported to Access and then ported to T-SQL). So I had to find a way. This is my solution. The following worked for me using Entity Framework 6.0 (the latest on NuGet as of this writing).
Right-click on your .edmx file in the Solution Explorer. Choose "Open With..." and then select "XML (Text) Editor". We're going to be hand-editing the auto-generated code here.
Look for a line like this:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
Remove store:Name="table_name" from the end.
Change store:Schema="whatever" to Schema="whatever"
Look below that line and find the <DefiningQuery> tag. It will have a big ol' select statement in it. Remove the tag and it's contents.
Now your line should look something like this:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
We have something else to change. Go through your file and find this:
<EntityType Name="table_name">
Nearby you'll probably see some commented text warning you that it didn't have a primary key identified, so the key has been inferred and the definition is a read-only table/view. You can leave it or delete it. I deleted it.
Below is the <Key> tag. This is what Entity Framework is going to use to do insert/update/deletes. SO MAKE SURE YOU DO THIS RIGHT. The property (or properties) in that tag need to indicate a uniquely identifiable row. For instance, let's say I know my table orders, while it doesn't have a primary key, is assured to only ever have one order number per customer.
So mine looks like:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Seriously, don't do this wrong. Let's say that even though there should never be duplicates, somehow two rows get into my system with the same order number and customer name. Whooops! That's what I get for not using a key! So I use Entity Framework to delete one. Because I know the duplicate is the only order put in today, I do this:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Guess what? I just deleted both the duplicate AND the original! That's because I told Entity Framework that order_number/cutomer_name was my primary key. So when I told it to remove duplicateOrder, what it did in the background was something like:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
And with that warning... you should now be good to go!

Entity Framework - Track changes and rollback

At the moment I've got a big Entity Data Model (.edmx) with a database underneath it. Now I want to give people who use my site the option to edit those entities but only after I gave approval of the change.
So this would mean that I want to "change" the entity but not really save it yet, after I accepted the change it would override the enity with the changed one. But when I did this I would still like to be able to rollback the change afterwards.
Now I've come up with a few solutions:
1) Make a entity with like: [ID], [ChangeApplyDate] [ChangeApproveDate] [Entity before change] [Entity after change] [Accepted (boolean)]
2) Make an extra entity with the changed values and a link to the "Original" entity and have a boolean in this entity if it is the current approved one or not. (this would not create a new table but expand the table like, "Book", with a few extra properties.
Now I would like to know how you think about those solutions and if you ever made something like this?
There are two things here:
Keep a list of all previous versions. Have a look at my answer to this question: Ideas on database design for capturing audit trails
Controll the acceptance of changes. To do this you could add an approval flag to each table, which only you have access to.

Where does the 'Name' property in a DBML come from?

I'm using Linq-To-Sql and inside my DBML there are objects built from the database connection provided.
If you click on an association line between two tables and view the properties on it, you will get the following:
Cardinality
Child Property
Access
Inheritance Modifier
Name
Parent Property
Access
Inheritance Modifier
Name
Participating Properties
Unique
My question is, where does Linq-To-Sql get the "Name" properties from? Where is the correlation to the actual database?
I ask this because if this table happens to be a parent to several children, Linq-To-Sql will just simply name these properties, "SomeParentName", "SomeParentName2", "SomeParentName3" , etc. So you'd have to go into the DBML and manually change these names to something meaningful every time you update this table.
Any help you can provide would be appreciated.
Part 2 of my question might be how do you guys handle these situations?
As for the Name: It takes the child / parent and comes up with something based on some internal voodoo. Don't ask me how.
As for Part 2: If you tend to have to redo stuff every time you update something I STRONGLY suggest switching to Entity Framework. It's very similar, but you can just hit "update" and your modifications are kept.

Categories