Get index of object in a list using Linq [duplicate] - linq

This question already has answers here:
How to get index using LINQ? [duplicate]
(7 answers)
Closed 8 years ago.
I am new to Linq. I have a Customers table.ID,FullName,Organization,Location being the columns. I have a query in Sqlite returning me 2500 records of customers. I have to find the index of the customer where ID=150 for example from this result set. Its a List of Customers. The result set of the query is ordered by organization. I tried with FindIndex and IndexOf but getting errors for the former and -1 for the latter. So, how should it be done?
Thanks.

You don't need to use LINQ, you can use FindIndex of List<T>:
int index = customers.FindIndex(c => c.ID == 150);

Linq to Objects has overloaded Select method
customers.Select((c,i) => new { Customer = c, Index = i })
.Where(x => x.Customer.ID == 150)
.Select(x => x.Index);
Keep in mind, that you should have in-memory List<Customer> to use this Linq to Objects method.

Related

Unable to perform Group join in linq in .net6 [duplicate]

This question already has answers here:
The LINQ expression 'Expression' could not be translated. Either rewrite the query in a form that can be translated
(1 answer)
Query with `groupjoin` cannot be translated although it's documened as being supported
(4 answers)
Can't make GroupJoin work. NavigationExpandingExpressionVisitor exception
(1 answer)
Group join in EF Core 3.1
(1 answer)
Closed 16 days ago.
I am working on a .net6 framework where querying database through linq to sql. I tried below Group Join in linq to fetch all the Orders against Products but getting an error. Can someone help me get out of this issue?
var result =
(from pd in dataContext.tblProducts
join od in dataContext.tblOrders on pd.ProductId equals od.ProductId
into t
select new
{
ProductId = pd.ProductId,
Orders = t.ToList()
}).ToList();
Exception:
Source - Microsoft.EntityFrameworkCore
Message - The LINQ expression 'DbSet<tblProducts>()
.GroupJoin(
inner: DbSet<tblOrders>(),
outerKeySelector: pd => pd.ProductId,
innerKeySelector: od => od.ProductId,
resultSelector: (p, o) => new {
ProductId= p.ProductId,
Orders = o.ToList()
})' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

LINQ to Entities does not recognize the method 'System.String PadLeft(Int32)' method [duplicate]

This question already has answers here:
LINQ to Entities does not recognize the method
(5 answers)
Closed 8 years ago.
please help me
What Should I do with this Error in this Code:
LINQ to Entities does not recognize the method 'System.String PadLeft(Int32)' method, and this method cannot be translated into a store expression.
var bookImagePage = (from bbs in LibCms.Books
join bbp in LibCms.BookPages on bbs.BookID equals bbp.BookID
select new
{
bbs.BookID,
bbp.VolumeNum,
bbs.AutolID,
bbp.PageNum,
a = bbs.AutoID.PadLeft(5, '0') + bbp.PageNo.PadLeft(4, '0')
}).Distinct().ToList();
You can't use methods in a Linq query. Take out the string manipulation then after ToList() add .Select(x=>new {
//now you can use methods on the results
})

Can I join a table to a list using linq? [duplicate]

This question already has answers here:
EntityFramework - contains query of composite key
(12 answers)
Closed 2 years ago.
I have a table as follows:
PersonalDetails
Columns are:
Name
BankName
BranchName
AccountNo
Address
I have another list that contains 'Name' and 'AccountNo'.
I have to find all the records from table that whose respective 'Name' and 'AccountNo' are present in given list.
Any suggestion will be helpful.
I have done following but not of much use:
var duplicationhecklist = dataAccessdup.MST_FarmerProfile
.Join(lstFarmerProfiles,
t => new { t.Name,t.AccountNo},
t1 => new { t1.Name, t1.AccountNo},
(t, t1) => new { t, t1 })
.Select(x => new {
x.t1.Name,
x.t1.BankName,
x.t1.BranchName,
x.t1.AccountNo
}).ToList();
where lstFarmerProfiles is a list.
You probably found out that you can't join an Entity Framework LINQ query with a local list of entity objects, because it can't be translated into SQL. I would preselect the database data on the account numbers only and then join in memory.
var accountNumbers = lstFarmerProfiles.Select(x => x.AccountNo).ToArray();
var duplicationChecklist =
from profile in dataAccessdup.MST_FarmerProfile
.Where(p => accountNumbers
.Contains(p.AccountNo))
.AsEnumerable() // Continue in memory
join param in lstFarmerProfiles on
new { profile.Name, profile.AccountNo} equals
new { param.Name, param.AccountNo}
select profile
So you will never pull the bulk data into memory but the smallest selection you can probably get to proceed with.
If accountNumbers contains thousands of items, you may consider using a better scalable chunky Contains method.
Since you have the lists in .net of values you want to find, try to use the Contains method, for sample:
List<string> names = /* list of names */;
List<string> accounts = /* list of account */;
var result = db.PersonalDetails.Where(x => names.Contains(x.Name) && accounts.Contains(x.AccountNo))
.ToList();
If MST_FarmerProfile is not super large I think you best option is to bring it into memory using AsEnumerable() and do the joining there.
var duplicationhecklist =
(from x in dataAccessdup.MST_FarmerProfile
.Select(z => new {
z.Name,
z.BankName,
z.BranchName,
z.AccountNo
}).AsEnumerable()
join y in lstFarmerProfiles
on new { x.Name, x.AccountNo} equals new { y.Name, y.AccountNo}
select x).ToList();
Since data is usually located on different machines or in separate processes at least: DB - is one and your in-memory list is your app, there is just 2 ways to do it.
Download as small data part from DB to local as possible and join locally (usually using AsEnumerable() or basically ToList()). You got many good thoughts on this in other answers.
Another one is different - upload your local data to server somehow and perform query on DB side. Uploading can be done differently: using some temp tables OR using VALUES. Fortunately there is a small extension for EF now (for both EF6 and EF Core) which you could try. It is EntityFrameworkCore.MemoryJoin (name might be confusing, but it supports both EF6 and EF Core). As stated in author's article it modifies SQL query passed to server and injects VALUES construction with data from your local list. And query is executed on DB server.
If accountNo identifies the record then you could use:
var duplicationCheck = from farmerProfile in dataAccessdup.MST_FarmerProfile
join farmerFromList in lstFarmerProfiles
on farmerProfile.AccountNo equals farmerFromList.AccountNo
select new {
farmerProfile.Name,
farmerProfile.BankName,
farmerProfile.BranchName,
farmerProfile.AccountNo
};
If you need to join on name and account then this should work:
var duplicationCheck = from farmerProfile in dataAccessdup.MST_FarmerProfile
join farmerFromList in lstFarmerProfiles
on new
{
accountNo = farmerProfile.AccountNo,
name = farmerProfile.Name
}
equals new
{
accountNo = farmerFromList.AccountNo,
name = farmerFromList.Name
}
select new
{
farmerProfile.Name,
farmerProfile.BankName,
farmerProfile.BranchName,
farmerProfile.AccountNo
};
If you are only going to go through duplicateChecklist once then leaving .ToList() out will be better for performance.

Entity Framework query

I have a piece of code that I don't know how to improve it.
I have two entities: EntityP and EntityC.
EntityP is the parent of EntityC. It is 1 to many relationship.
EntityP has a property depending on a property of all its attached EntityC.
I need to load a list of EntityP with the property set correctly. So I wrote a piece of code to get the EntityP List first.It's called entityP_List. Then as I wrote below, I loop through the entityP_List and for each of them, I query the database with a "any" function which will eventually be translated to "NOT EXIST" sql query. The reason I use this is that I don't want to load all the attached entityC from database to memory, because I only need the aggregation value of their property. But the problem here is, the looping will query the databae many times, for each EntityP!
So I am wondering if anybody can help me improve the code to query the database only once to get all the EntityP.IsAll_C_Complete set, without load EntityC to memory.
foreach(EntityP p in entityP_List)
{
isAnyNotComoplete = entities.entityC.Any(c => c.IsComplete==false && c.parent.ID == p.ID);
p.IsAll_C_Complete = !isAnyNotComoplete;
}
Thank you very much!
In EF 4, you can do:
var ids = entityP_List.Select(p => p.ID);
var q = (from p in entities.entityP
where ids.Contains(p => p.ID)
select new
{
ID = p.ID,
IsAll_C_Complete = !p.entityCs.Any(c => !c.IsComplete)
}).ToList();
foreach (var p in entityP_List)
{
p.IsAll_C_Complete = q.Where(e.ID == p.Id).Single().IsAll_C_Complete;
}
...which will do the whole thing in one DB query. For EF 1, Google BuildContainsExpression for a replacement for the .Contains( part of the above.
I would base EntityP on a SQL View instead of a table. Then I would define the relationship, and aggregate the value for child table within the view.

Best way to delete multiple records in a LINQ query? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 months ago.
Improve this question
What is the best way to remove multiple records in one go with LINQ?
To delete records with Linq2Sql
CustomerDataContext ctx = new CustomerDataContext("connection string");
var customers = ctx.Customers.Where(c => c.Name == "david");
ctx.Customers.DeleteAllOnSubmit(customers);
ctx.SubmitChanges();
Using entity framework 6
using (EntitiesContext db = new EntitiesContext(connString))
{
// Retrieve all records from database for deletion
IEnumerable<entity> entityList = db.entity.where(x => x.id == id).toList();
// Use Remove Range function to delete all records at once
db.entity.RemoveRange(entityList);
// Save changes
db.SaveChanges();
}
The good old SPROCs.....
You can drag the SPROC to your DBML file and it will generate a rich method in your databasecontext class.
How to: Call a Stored Procedure by Using LINQ (Visual Basic)
LINQ and Stored Procedures
Here is How I solved the problem :
try
{
List<MaterialPartSerialNumber> list = db.MaterialPartSerialNumbers.Where(s => s.PartId == PartId && s.InventoryLocationId == NewInventoryLocationId && s.LocationId == LocationId).ToList();
db.MaterialPartSerialNumbers.RemoveRange(list);
db.SaveChanges();
}
catch(Exception ex)
{
string error = ex.Message;
}
First, you can find a list of the items you want to delete.
Then, you can use the function RemoveRange(**list_of_item_to_delete**) so that it removes each instance in the list present in the database.
According to the MSDN, the method removes a range of elements from the List.
For more information, check it here https://msdn.microsoft.com/en-us/library/y33yd2b5(v=vs.110).aspx
Removing many records based on single where clause
context.EntityModel
.RemoveAll(r => r.property == "propertyEntered");
But you could also Remove records from the database that don't exist in List<ListOfBadRecords>
context.EntityModel
.Where(w => w.propertyID == ID).ToList()
.RemoveAll(r => !ListOfBadRecords.Any(a => a.anyID == r.propertyID ));
Edit:
Unsure wich is quicker but you could do the 2nd query with this also
.RemoveAll(r => !ListOfBadRecords.Select(s=>s.propertyID ).Contains(w.propertyID ))
Edit2: don't forget context.SaveChanges(); as i did in the first draft
This is what I used, first create an IENumerable object of the table where are the records to be removed are, then just use RemoveRange, and finally just save changes to database. Let's say you want to remove all products from one specific supplier ID on the Products table, this is how you could do that.
IEnumerable<Products> ProductsToRemove= db.Products.Where(x => x.SupplierId== Supplierid);
db.Products.RemoveRange(ProductsToRemove);
db.SaveChanges();
maybe its litle late for this answer but today I ran into this demand myself I and I came up with this solution
CustomerDataContext ctx = new CustomerDataContext("connection string");
ctx.Customers.DeleteAllOnSubmit(ctx.Customers.Where(c => c.Name == "david"));
ctx.SubmitChanges();
I agree with Khurram, it's much more efficient to do this with a simple stored procedure with LINQ (provided you have sufficient permissions in SQL to do this). I'll augment this with an example.
The stored procedure:
CREATE PROCEDURE [dbo].[RemovePermissionsFromRole]
(
#ROLE_ID int
)
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM [RolePermissions] WHERE [RoleID] = #ROLE_ID;
END
Drag the stored procedure from the database explorer onto the methods pane in your DBML file. Save the file. And in code:
if (Request.QueryString["RoleID"] != null) {
int roleID = Convert.ToInt32(Request.QueryString["RoleID"]);
SETSDataContext context = new SETSDataContext();
context.RemovePermissionsFromRole(roleID);
}
With just Entity Framework I found this to be the tightest code.
db.PreperProperties.RemoveRange(db.PreperProperties.Where(c => c.preperFk == prpr.id));
db.SaveChanges();

Resources