How can I do more than one level of cascading deletes in Linq? - linq

If I have a Customers table linked to an Orders table, and I want to delete a customer and its corresponding orders, then I can do:
dataContext.Orders.DeleteAllOnSubmit(customer.Orders);
dataContext.Customers.DeleteOnSubmit(customer);
...which is great. However, what if I also have an OrderItems table, and I want to delete the order items for each of the orders deleted?
I can see how I could use DeleteAllOnSubmit to cause the deletion of all the order items for a single order, but how can I do it for all the orders?

You might wish to consider using on delete cascade on the foreign key relationship in the database rather then using LINQ to do it. If you wish to use LINQ then
customer.Orders.ForEach(x => x.OrderItems.ForEach(y=> dataContext.OrderItems.Delete(y));
dataContext.Orders.DeleteAllOnSubmit(customer.Orders);
dataContext.Customers.DeleteOnSubmit(customer);
should do it but I haven't tested it.

Related

Laravel models, database and pivot tables question

Hello I am working with Laravel,
I have to create two simple models, let's say Stores and Books.
Stores can have one or multiple Books and Books can belong to many Stores.
Of course I will use a many to many relationship, with a pivot table.
Books the can have different prices depending the store.
I think a separate table can only complicate things, in my mind the pivot table associating books and stores should have a price column, but pivot tables only contains store_id and book_id.
Should I create a book_prices and associate it with books and to stores? What is the best approach?
You are free and able to set other attributes on your pivot table. You can read more about it in the docs.
https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns
You have to define the relationship accordingly, the following should clarify how this works. In this example you use the many-to-many relationship and add the price column to every retrieved pivot model.
public function books()
{
return $this->belongsToMany(Book::class)
->withPivot('price')
}
For example, you are able to access the pivot column in a loop like this
foreach ($shop->books as $book)
{
echo $book->pivot->price;
}
You can define additional columns for your pivot table in the migration for the pivot table, and then when defining the relationship use withPivot to define the additional columns so they come through in the model:
return $this->belongsToMany(Book::class)->withPivot('price');
(Adapted from the Laravel documentation, see https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns)
Depends on the complexity of your case, but yes, you have two options for it. Let's say that the pivot table is called as book_store:
Directly adds price column to book_store. This is obviously the simpler option. The drawbacks are:
The history of the price changes isn't logged. You'll have to create another table for logging if you want to keep this history information.
Changes made to price will directly change the price of the related book_store record. Meaning that a price is being updated "live" e.g users cannot update the price now but "publish" it some time later just like this example in the doc.
Create a new, different table to store the price. This may seems relatively more complex, but it may also be more future-proof.
Basically, you get 2 things that you miss in the first option above.
Don't think too much about book_store being a pivot table. One way to see it is like this: book_store IS a pivot table from books and stores tables viewpoints, but it's also just a normal SQL table which could relate to any other tables using any kind of relationships.
If you want to implement this, make sure to create a primary-key in the book_store table.
Alast, it all depends on what you need. Feel free to ask if you need more insight about this. I hope this helps.

Update then delete child table's value on deleting parent record Laravel

I have two tables Order and OrderItem where OrderItem has the order_id as foreign key from Orders table. I have used laravel relationship in each of their model. Upon deleting a record from Order table which has relation in the OrderItem, I want to update a column name "Cancel" to true in OrderItem table and then soft delete the record.
I only know the manual method where I find the record by id, then update and soft delete it. Can anyone help me with shorter and easier method? Thank you.
I think you're mean is soft delete.
you can see this document.

Any way to intercept an error message and make more user friendly?

I have looked for an answer here among other places but havent quite been able to find what I need to know.
I have 3 tables, Order_Details, Products_Ordered and Product_Details. The first two are being used in a master detail form to show the order and the items ordered together. The Products_Ordered table has a composite primary key made from two foreign keys, the first being the primary key from the Order_Details table, and the second being the primary key from the Product_Details table. Together they ensure that a type of product can only be added to an order once. If someone wants to order more than one product then the quantity field in the record can be altered to reflect this. All that seems fine so far.
My issue is that when adding products to the order in the master detail form i have used a drop down list of values to select the product to add to the order. the display value for this is the product name and the return value for it is the primary key for the product from the Product_Details table.
I like this because its easier for the user to simply select the product and add a quantity of it to the table. And it works fine for both insert and update operations apart from one situation.
If the user selects the same product in to rows then submits the table the database then tries to add the product to the order twice, throwing a "ORA-00001: unique constraint violated." error. Obviously this is because of the product ID being used in the primary key of the table.
I don't want to allow the user to add two records to the table like that, rather id like to force them to alter the quantity field accordingly. The error message that comes up isn't very user friendly so my question is how can I detect this error and display a more user friendly one instead telling them to alter the quantity field instead?
*If this isn't possible then is there a way that I can hide any already selected products from the dropdown list of values in the following table rows? I haven't looked into this too much because surely it would get complicated when the user tries to add more rows than products available in the dropdown and there are no more products values to show?
I am quite new to this so please be nice. Any help is greatly appreciated :D
Here is a link where all is nicely described:
https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/07_errs.htm
Section
Predefined PL/SQL Exceptions
in combination with:
Defining Your Own PL/SQL Exceptions
and
Defining Your Own Error Messages: Procedure RAISE_APPLICATION_ERROR
Hope it helps...

How to get most repetitive values with Eloquent?

I have relation many to many (posts and tags) in Eloquent. Is it possible to order tags in the pivot table to get 10 most commonly used tags?
Yes it is possible, add some kind of attribute (to the pivot table and update it upon every select from the database. (increment the value)
And when selecting use wherePivot method.
If you want "most recent used", add timestamps to the pivot table in your migration and touch pivot table on every select.
Yes it is actually very simple to do that.
In the table that you store your tags add another column called count_cache(or whatever you want), then every time you add a tag instance to a post instance do a count() of the tag_id in the pivot table and store the value to the count_cache column in the tags table.
Then you can simply get the tags table ordered by the count_cache collumn (descending) with a limit of 10.
If you need further explanation please make a comment :)

Using LINQ to delete child records automatically

I am somewhat new to LINQ and have a quick question regarding deleting.
Say, for example I have 2 tables, Orders and OrderItems. Using LINQ, I can easily create a new child record by using
order.Items.Add(new OrderItem());
and this will create the child record in the database and update its foreign key to the orderId. This is great, I like it! However when I want to remove a child record
order.Items.Remove(orderItem);
I get an error when I sumbit the changes (because its not actually deleting the child row (order item), just removing the foreign keyId). Is it possible to do this the way I would like to? I don't want to have to create a whole bunch of repositories and if ladders to delete all child rows for a large database.
Thanks in advance.
E
You can achieve that in the DB itself by configuring the Foreign key relationship to delete child records on deletion of the parent's key.
Note that this is transparent to Linq2SQL and it will not be aware of it, so it's best to make sure you do not keep the datacontexts around after that, since the OrderItem objects will still be present.
Set ON DELETE CASCADE for the table in question which will let the SQL Server handle this for you.

Resources