Delete multiple rows using Entity Framework - entity-framework-core

When deleting data related to an object in an HttpDelete call using Entity Framework Core, I can do this:
var video = _context.VideoList.Where(x => x.VideoId == nodeList.VideoId).FirstOrDefault();
But what if I have multiple rows that needed deleted using the same VideoId? Also the two entities are not related in the database(no foreign keys).
I've found answers that use a List then use RemoveRange, but I just need to delete potentially multiple records using the same ID...I know in SQL it would look like this:
DELETE FROM VideoList WHERE VideoId = '111xxx333aaa'
Is there a way to do this in EF core?
Thanks!

You can do it in 2 steps :
Even if your entities are not related get them in an IEnumerable like a List
var videos = _context.VideoList.Where(x => x.VideoId == nodeList.VideoId).ToList();
And then remove them with a RemoveRange
_context.VideoList.RemoveRange(videos);

Related

Use GetAllIncluding to get multiple levels in a single call

Using ABP Repository pattern we are trying to create a single query to retrieve a set of entities, along with their children, and the childrens children
Entity X -> one to many Entity Y -> one to many Entity Z
(think Invoice > InvoiceItem > InvoiceItemParts for example)
The Abp repository pattern provides for retrieving at least 1 set of children using
result = _repositoryInvoice.GetAllIncluding(x => x.InvoiceItem)
is there a way using LINQ to include InvoiceItemParts in this 1 query? If not, what is the recommended way to retrieve all child nav properties and all levels using a single call.
The main goal is making it so we don't have to make multiple round trips to the DB when accessing the child properties along with the child properties of those children.
thanks
jasen
Decided to just create my own custom repository and use EFCore .Include and .ThenInclude directly. Turns out AspNetBoilerPlate has no support for querying navigation properties beyond their immediate children of the root entity being queried.
Microsoft provides some great examples of using .Include and .ThenInclude:
https://learn.microsoft.com/en-us/ef/core/querying/related-data
Good luck!
GetAllIncluding accepts params, so you can specify multiple attributes:
var result = await _repositoryInvoice
.GetAllIncluding(x => x.InvoiceItem,
x => x.InvoiceItemParts)
.ToListAsync();
With IRepository<> there are the method Include and ThenInclude, where you can use the same structure of EF Core standard.
_repository.GetAll().Include(d => d.Child).ThenInclude(c => c.GrandChild).FirstOrDefault(x => x.Id.Equals(id));

Delete link table entry but not referenced table entries

I am using Entity Framework database-first model. I have 2 tables that are referenced by a link table.
For example:
When I update my edmx file from my database this creates the expected model:
Now what I want to do is delete an entry from the Product_User table without deleting the referenced entry in either of the related tables (Product or User).
I've tried both of these statements (together and separately) but neither seems to have any effect:
user.Products.Clear();
foreach (var product in products)
{
product.User = null;
}
Is what I'm trying to do possible with the model the way I have it now? And if so what am I doing wrong?
I noticed I can do what I'm trying to do if I add the link table explicitly to the model but I'm trying to avoid that.
Any help would be much appreciated. Thanks.
Your seconde way to go (with a loop) seems more like the correct way.
Instead of = null try to use the .Remove() function. I guess the remove function only remove the link between the two entity, not the entities related.
See this answer : Removing many to many entity Framework

EF 4 delete many to many object

I am trying to delete an object from a many to many relationship but it refused to get worked.
The structure is as follows:
I have a Products table which every product has excProducts
I am trying to delete an excProduct with the following code
var objectContx = new objectContx();
var prod = objectContx.Products.Where(p => p.ProductID == prodID).FirstOrDefault();
var excProd = objectContx.ExcProducts.Where(exc => exc.ExcProductID == excProdid).FirstOrDefault();
prod.ExcProducts.Attach(excProd);
prod.ExcProducts.Remove(excProd);
objectContx.SaveChanges();
The excProd deleted from database but when I am getting the Product from objectContext it has the deleted excProd in it's list.
How could I delete it from the objectContext as well?
If your many to many relationship has an entity (e.g. if it has payload) then the instance of that entity must be deleted. This can be done manually or using cascaded delete (see option in property window while standing on relationship in EDMX designer).

Wide and narrow versions of an entity mapped to one table in Entity Framework

In some scenarios I need a "wide" version of an entity with many properties (say FullCustomer) while in other scenarios it's enough with a "narrow" version with few properties (say MiniCustomer), how could I map these two entities, FullCustomer and MiniCustomer, to the same Customer table in the database? Furthermore, I need to be able to query and update both entities.
Thanks in advance for any advice or pointers!
PD. I'm using VS2010 RC and EF 4
For "efficiency", don't have two versions of the entity; just project onto "lite" POCOs:
var q = from e in Context.Entities
select new LitePoco
{
Id = e.Id,
EditThis = e.EditThis
};
No other columns will be returned.
Similarly for save:
var e = new MyEntity { Id = 123 };
Context.AttachTo("Entities", e);
// anything from here on gets saved
e.EditThis = "Edited";
Context.SaveChanges();
If you have a column that determines whether to treat the record as a FullCustomer or as MiniCustomer, then you can easily create a Table per Hierarchy inheritance model with FullCustomer inherited from MiniCustomer. Such approach is described in the Muhammad Mosa's blog post.
If you don't have this column you can update the model and database in order to add it.
However, there is an alternative approach. If the reason to have two entities for one table is the delay in the loading the numerous large properties in the FullCustomer object, than Table Splitting might be an option. Take a look at the Julie Lerman's blog post.
I would have noted that this problem is not present in ORMs like LINQ to SQL, due to deferred loading.

Adding & Removing Associations - Entity Framework

I'm trying to get to grips with EF this week and I'm going ok so far but I've just hit my first major snag. I have a table of items and a table of categories. Each item can be 'tagged' with many categories so I created a link table. Two columns, one the primary ID of the item, the other the primary ID of the category. I added some data manually to the DB and I can query it all fine through EF in my code.
Now I want to 'tag' a new item with one of the existing categories. I have the category ID to add and the ID of the Item. I load both as entities using linq and then try the following.
int categoryToAddId = Convert.ToInt32(ddlCategoriesRemaining.SelectedValue);
var categoryToAdd = db.CollectionCategorySet.First(x => x.ID == categoryToAddId);
currentCollectionItem.Categories.Add(categoryToAdd);
db.SaveChanges();
But I get "Unable to update the EntitySet 'collectionItemCategories' because it has a DefiningQuery and no element exists in the element to support the current operation."
Have I missed something? Is this not the right way to do it? I try the same thing for removing and no luck there either.
I think I have managed to answer this one myself. After alot of digging around it turns out that the Entity Framework (as it comes in VS2008 SP1) doesn't actually support many to many relationships very well. The framework does create a list of objects from another object through the relationship which is very nice but when it comes to adding and removing the relationships this can't be done very easily. You need to write your own stored procedures to do this and then register them with Entity Framework using the Function Import route.
There is also a further problem with this route in that function imports that don't return anything such as adding a many to many relationship don't get added to the object context. So when your writing code you can't just use them as you would expect.
For now I'm going to simply stick to executing these procedures in the old fashioned way using executenonquery(). Apparently better support for this is supposed to arrive in VS2010.
If anyone feels I have got my facts wrong please feel free to put me right.
After you have created your Item object, you need to set the Item object to the Category object on the Item's Categories property. If you are adding a new Item object, do something like this:
Using (YourContext ctx = new YourContext())
{
//Create new Item object
Item oItem = new Item();
//Generate new Guid for Item object (sample)
oItem.ID = new Guid();
//Assign a new Title for Item object (sample)
oItem.Title = "Some Title";
//Get the CategoryID to apply to the new Item from a DropDownList
int categoryToAddId = Convert.ToInt32(ddlCategoriesRemaining.SelectedValue);
//Instantiate a Category object where Category equals categoryToAddId
var oCategory = db.CategorySet.First(x => x.ID == categoryToAddId);
//Set Item object's Categories property to the Category object
oItem.Categories = oCategory;
//Add new Item object to db context for saving
ctx.AddtoItemSet(oItem);
//Save to Database
ctx.SaveChanges();
}
Have you put foreign keys on both columns in your link table to the item and the category or defined the relationship as many to many in the Mapping Details?