Except keyword issue in LINQ - linq

I want to capture the column names which needs to be added to the SQL table in order to insert the data.
Columnspresent-- List of all columns in the file ("Node", "Logtime", "Reason","ID","Comments")
existingtablecolumnsPresent -- List of all columns in the existing table in SQL("Node","Value","Reason","ID","Comments","logtime")
columnsNotPresent -- List of columns that needs to be added to the SQL table ( have to get "Value" in the output but not getting)..
List<string> columnsPresent =
dt.Columns.Cast<DataColumn>()
.Select(a => a.ColumnName.ToLower())
.ToList();
List<string> existingtablecolumnsPresent =
existingtable.Columns.Cast<DataColumn>()
.Select(a => "[" + a.ColumnName.ToLower() + "]")
.ToList();
List<string> columnsNotPresent =
columnsPresent.OrderBy(t => t)
.Except(existingtablecolumnsPresent.OrderBy(t => t))
.ToList();
The above code is not giving the correct results if there is change in order of columns .Please advise.

you may try this (it needn't order by..)
List<string> existingtablecolumnsPresentNoSqrBr = new List<string>();
existingtablecolumnsPresent.ForEach(c => {
c = c.Replace("[", string.Empty);
c = c.Replace("]",string.Empty);
existingtablecolumnsPresentNoSqrBr.Add(c);
});
List<string> columnsNotPresent =
columnsPresent.Except(existingtablecolumnsPresentNoSqrBr)
.ToList();
really, if you avoid to .Select(a => "[" + a.ColumnName.ToLower() + "]") you can use the second query directly on existingtablecolumnsPresent..

Related

Get distinct value from database

I want to get the distinct list of studentname from the database who are still active. Ihis is what I've tried.
string strJSON = JsonConvert.SerializeObject(
context.Students.Where(x => x.IsActive == 1).Distinct().ToList());
Distinct function works on all columns, so I assume that you want only student name.
string strJSON = JsonConvert.SerializeObject(
context
.Students
.Where(x => x.IsActive==1)
.Select(x=>x.StudentName)
.Distinct()
.ToList()
);

Dynamic sorting with nullable column

I am writing dynamic sorting with lambda expression as below:
string sortColumn = imageFilterType == 1 ? "CreatedDate" : "AbuseCount";
var paramExp = Expression.Parameter(typeof(Items), typeof(Items).ToString());
Expression propConvExp = Expression.Convert(Expression.Property(paramExp, sortColumn), typeof(object));
var sortExp = Expression.Lambda<Func<Items, object>>(propConvExp, paramExp);
Above I am creating dynamic sort column and I am applying this sortexpression in bellow query:
var items = _db.Items.AsQueryable()
.AsExpandable()
.OrderByDescending(sortExp)
.Where(predicate)
.Select(x => x)
.Join(_db.Users, i => i.UserId, u => u.UserID, (i, u) => new
{
i,
FullName = u.UserType == 1 ? u.FirstName + " " + u.LastName : u.CompanyName,
u.UserType,
u.UserName
})
.ToList()
.Skip(pageIndex)
.Take(pageSize);
I have 2 columns in input by which I have to sort data one is CreatedDate and another is Abusecount. I have to apply sorting with one column among both of them. but as I am trying to run above code I am getting error:
"Unable to cast the type 'System.Nullable`1' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types."
Since in my database both column is of nullable type thatswhy I am getting this problem. Is anyone have solution of this problem? I don't want to change in DB. I have to solve it from fron end only.
Try this, it's much simplier:
var items = _db.Items.AsQueryable()
.AsExpandable();
if (imageFilterType == 1)
items=items.OrderByDescending(a=>a.CreatedDate);
else
items=items.OrderByDescending(a=>a.AbuseCount);
items=items.Where(predicate)
.Select(x => x)
.Join(_db.Users, i => i.UserId, u => u.UserID, (i, u) => new
{
i,
FullName = u.UserType == 1 ? u.FirstName + " " + u.LastName : u.CompanyName,
u.UserType,
u.UserName
})
.Skip(pageIndex)
.Take(pageSize)
.ToList();

Split into KeyValuePair instead of Array

I have a string of data:
Key1=Value1,Key2=Value2,KeyN=ValueN
I'm trying to split the string into
List<KeyValuePair<string, string>>
I can easily do this:
List<string[]> values = item.Split( ',' ).Select( p => p.Split( '=' ) ).ToList();
but I just can't figure out the way to get that into the List of KeyValuePair's. The closest I've gotten so far is:
List<KeyValuePair<string, string>> values = item.Split( ',' )
.Select( p => new KeyValuePair<string, string>(){ p.Split( '=' ) } ).ToList();
But that's still a bit off :(
I know I can easily do it with a loop but I'd really like to get it working in Linq as practice makes perfect. I've seen quite a few examples already of similar questions like this one, but I can't seem to join the dots between those questions and mine so please forgive me if I've accidentally posted a duplicate.
Any help would really be appreciated, thanks :)
What you've done so far is good. Then, you have two ways to achieve what you want:
Create a method ToKeyValuePair
public static KeyValuePair<string, string> ToKeyValuePair(string[] array)
{
if (array.Length != 2)
throw new ArgumentException("The array must contain exactly 2 elements.");
return new KeyValuePair<string, string>(array[0], array[1]);
}
var values = (item.Split( ',' )
.Select( p => ToKeyValuePair(p.Split( '=' ))))
.ToList();
Use the LINQ query syntax
If I convert the above line into query syntax:
var values = (from p in item.Split( ',' )
select ToKeyValuePair(p.Split( '=' )))
.ToList();
Not much has changed.
But, thanks to this new syntax, it is quite easy to remove the usage of ToKeyValuePair(...) thanks to the let clause:
var values = (from p in item.Split( ',' )
let splittedP = p.Split( '=' ) // Declares a variable
select new KeyValuePair<string, string>(splittedP[0], splittedP[1]))
.ToList();
Of course, the last line can be written with Extention methods syntax (ie with .Select(p=>...)), but is hard to read:
var values = (item.Split(',')
.Select(p => new { p, splittedP = p.Split('=') })
.Select(p => new KeyValuePair<string, string>(p.splittedP[0], p.splittedP[1])))
.ToList();
I know this is an old question but I stumbled across it on google. I solved the problem using the accepted answer but a shortened it a little. You don't need the new { p, splittedP = p.Split('=') } part, just p.Split('=')
var values = data.Split(',').Select(p=>p.Split('='))
.Select(s => new KeyValuePair<string, string>(s[0], s[1]))
.ToList();
You could also do something like this if your keys are unique:
var values = data.Split(',').Select(p => p.Split('='))
.ToDictionary(k => k[0], v => v[1]);
Which is much shorter and basically gets you a list with with O(1) access.
(This is with .NET 4.5)
use above code. must trim the key.
public static string GetUserInfo(this X509Certificate2 x509,X509Oid oid)
{
try
{
var kvs = x509.Subject.Split(',').Select(x => new KeyValuePair<string, string>(x.Split('=')[0].Trim(), x.Split('=')[1].Trim())).ToList();
string value = kvs.FirstOrDefault(A => A.Key == oid.ToString()).Value;
return value;
}
catch (Exception)
{
}
return "";
}
Add an enum file.
public enum X509Oid
{
O,
E,
L,
C,
S,
G,
SN,
CN,
Street
}

How to find all rows of items that have a part in common using LINQ?

I need to return all records (items) that has a part (X) so I can use that in a group or .GroupBy afterwards
Using this summary data:
ItemName PartName
1 A
1 B
2 A
3 C
So Item1 has two parts (A,B), etc...
I need a LINQ query that will
- find all items that have part A (i.e items 1 and 2)
- return all rows for all these items
1 A
1 B
2 A
Notice that the end result returned the row (1 B) because Item1 has PartA and so I need to get back all rows for Item1.
I was looking at something like:
let items = from data in summary where data.PartName == A select new { data.ItemName } // to get all the items I need
But then, now that I have that list I need to use it to get all the rows for all items listed, and I can't seem to figure it out ...
Actual Source Code (for reference):
NOTE:
Recipe = ITEM
Ingredient = PART
(I was just trying to make it simpler)
ViewFullRecipeGrouping = (
from data in ViewRecipeSummary
group data by data.RecipeName into recipeGroup
let fullIngredientGroups = recipeGroup.GroupBy(x => x.IngredientName)
select new ViewFullRecipe()
{
RecipeName = recipeGroup.Key,
RecipeIngredients = (
from ingredientGroup in fullIngredientGroups
select new GroupIngredient()
{
IngredientName = ingredientGroup.Key
}
).ToList(),
ViewGroupRecipes = (
from data in ViewRecipeSummary
// this is where I am looking to add the new logic to define something I can then use within the next select statement that has the right data based on the information I got earlier in this query.
let a = ViewRecipeSummary.GroupBy(x => x.RecipeName)
.Where(g => g.Any(x => x.IngredientName == recipeGroup.Key))
.Select(g => new ViewRecipe()
{
RecipeName = g.Key,
IngredientName = g.Select(x => x.IngredientName)
})
select new GroupRecipe()
{
// use the new stuff here
}).ToList(),
}).ToList();
Any help would be much appreciated.
Thanks,
I believe this does what you want:
var data = /* enumerable containing rows in your table */;
var part = "X";
var items = new HashSet<int>(data
.Where(x => x.PartName == part)
.Select(x => x.ItemName));
var query = data.Where(x => items.Contains(x.ItemName));
If I understand your comment at the end, I believe this also does what you want:
var query = data
.GroupBy(x => x.ItemName)
.Where(g => g.Any(x => x.PartName == part))
.Select(g => new
{
ItemName = g.Key,
PartNames = g.Select(x => x.PartName)
});

Link OrderBy method not taking effect after Union method

I'm using LINQ's Union method to combine two or more collections. After that I'm trying to apply sorting to the combined collection by calling OrderBy on a field that is common to the collections. Here is how I am applying sorting:
combinedCollection.OrderBy(row => row["common_field"]);
combinedCollection is defined as:
Enumerable<DataRow> combinedCollection;
I need the sorting to be applied to the entire combined collection. For some reason, that is not happening. Instead I see there is sorting applied on some other field separately within each 'collection' block within the combined collection
And idea why??
First Edit
foreach (....)
{
if (combinedCollection != null)
{
combinedCollection = combinedCollection.Union(aCollection);
}
else
{
combinedCollection = aCollection;
}
}
Second Edit
_Cmd.CommandText = "SELECT Person.Contact.FirstName, Person.Contact.LastName, Person.Address.City, DATEDIFF(YY, HumanResources.Employee.BirthDate, GETDATE()) AS Age"
+ " FROM HumanResources.EmployeeAddress INNER JOIN"
+ " HumanResources.Employee ON HumanResources.EmployeeAddress.EmployeeID = HumanResources.Employee.EmployeeID INNER JOIN"
+ " Person.Address ON HumanResources.EmployeeAddress.AddressID = Person.Address.AddressID INNER JOIN"
+ " Person.Contact ON HumanResources.Employee.ContactID = Person.Contact.ContactID AND HumanResources.Employee.ContactID = Person.Contact.ContactID AND "
+ " HumanResources.Employee.ContactID = Person.Contact.ContactID AND HumanResources.Employee.ContactID = Person.Contact.ContactID";
DataTable employeeTable = new DataTable();
_Adpt.Fill(employeeTable);
DataRow[] allRows = null;
allRows = employeeTable.Select("");
IEnumerable<DataRow> filteredEmployeeRows;
filteredEmployeeRows = from row in allRows select row;
// Declare a variable to hold the city-filtered rows and set it to null for now
IEnumerable<DataRow> cityFilteredEmployeeRows = null;
//Copy filtered rows into a data table
DataTable filteredEmployeeTable = filteredEmployeeRows.CopyToDataTable<DataRow>();
foreach (DataRowView city in CityListBox.SelectedItems)
{
// create an exact copy of the data table
DataTable filteredEmployeeCopyTable = filteredEmployeeTable.Copy();
// Enumerate it
IEnumerable<DataRow> filteredEmployeeRowsInSingleCity = filteredEmployeeCopyTable.AsEnumerable();
// Apply the city filter
filteredEmployeeRowsInSingleCity = _ApplyCityFilter(filteredEmployeeRowsInSingleCity, city["City"].ToString());
if (cityFilteredEmployeeRows != null)
{
// Combine the filtered rows for this city with the overall collection of rows
cityFilteredEmployeeRows = cityFilteredEmployeeRows.Union(filteredEmployeeRowsInSingleCity);
}
else
{
cityFilteredEmployeeRows = filteredEmployeeRowsInSingleCity;
}
}
//apply ordering
cityFilteredEmployeeRows.OrderBy(row => row["Age"]);
//cityFilteredEmployeeRows.OrderByDescending(row => row["Age"]);
EmployeeGridView.DataSource = cityFilteredEmployeeRows.CopyToDataTable<DataRow>();
.......
private IEnumerable<DataRow> _ApplyCityFilter(IEnumerable<DataRow> filteredEmployeeRows, string city)
{
IEnumerable<DataRow> temp = filteredEmployeeRows;
filteredEmployeeRows = from row in temp
where row["City"].ToString() == city
select row;
return filteredEmployeeRows;
}
I think you have a problem with the LINQ lazy evaluation, I would have to investigate to find out wich part causes the problem.
Using the foreach(var item...) in lazy functions has already bitten me (because when executed later they all reference the last iterated item), but in your case it doesn't look like this is the problem.
To check it is the really the issue you can just use a DataRow[] in place of the IEnumerable<DataRow> and call .ToArray() after every LINQ function.
Edit: I'm not sure I got your code right but can't you just use:
var cities = CityListBox.SelectedItems.Cast<DataRowView>()
.Select(city => city["City"].ToString())
.ToArray();
var rows = allRows
.Where(r => cities.Contains((string)r["City"]))
.OrderBy(r => (int?)r["Age"])
.ToArray(); // if you want to evaluate directly, not mandatory

Resources