NDepend: how to export the result from a query - linq

I've got a CQLinq query which returns a list of methods and a list of members for each of them. Exporting the query result will only show the number of elements. I thought about using a Linq Aggregate( (a,b) => a + ',' + b). Is there a better solution?
let type = Application.Types.WithFullName("WPF.ViewModels.CouponViewModel").Single()
let dicoFields = type.Fields
.ToDictionary(f => f, f => f.MethodsUsingMe.Where(m => m.ParentType == f.ParentType))
let dicoMethods = type.Methods
.ToDictionary(m => m, m => m.MembersUsed.Where(f => f.ParentType == m.ParentType))
// The partition algorithm on both dicos here
//from pair in dicoFields
//orderby pair.Value.Count() descending
//select new { pair.Key, pair.Value }
from pair in dicoMethods
orderby pair.Value.Count() descending
select new { pair.Key, pair.Value}

Indeed you can rewrite your query this way:
let type = Application.Types.WithFullName("WPF.ViewModels.CouponViewModel").Single()
let dicoMembers = type.ChildMembers
.ToDictionary(x => x, x =>
x.IsField ? x.AsField.MethodsUsingMe.Where(m => m.ParentType == x.ParentType):
x.AsMethod.MembersUsed.Where(f => f.ParentType == x.ParentType))
from pair in dicoMembers
orderby pair.Value.Count() descending
select new {
pair.Key,
str = pair.Value.Any() ?
pair.Value.Select(x => x.Name).Aggregate( (a,b) => a + " ; " + b) :
"empty"
}
Both methods and fields are taken account
Methods using fields and members used by methods are aggregated in a string
Then you can export the result:

Related

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();

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)
});

linq groupjoin using lambda with a where clause

I need to add a join using Lambda if I have a further parameter available that will also be used in a where clause.
My problem is I'm not sure of the exact format for adding a new object MemberTagLysts and then how the where clause should be created.
var tagList = from t in dc.Tags
join b in dc.Businesses on t.BusinessId equals b.BusinessId
where t.IsActive == true
where b.IsActive == true
orderby t.AdImage descending
select new TagItem
{
tagName = t.Name.Replace("\"", ""),
tagImage = tagImagePath + t.AdImage.Replace("\"", ""),
tagDescription = t.Description.Replace("\"", "")
};
if (!string.IsNullOrEmpty(lystId))
{
tagList = (IQueryable<TagItem>)tagList.GroupJoin(dc.MemberTagLysts, a => a.tagId, b => b.TagId, (a, b) => new { a, b });
}
I think you want to do something like this:
var tagList = from t in dc.Tags
join b in dc.Businesses on t.BusinessId equals b.BusinessId
where t.IsActive
where b.IsActive
orderby t.AdImage descending
select new TagItem
{
tagName = t.Name.Replace("\"", ""),
tagImage = tagImagePath + t.AdImage.Replace("\"", ""),
tagDescription = t.Description.Replace("\"", "")
};
if (!string.IsNullOrEmpty(lystId))
{
tagList = tagList
.GroupJoin(dc.MemberTagLysts.Where(l => l.lystId == lystId),
a => a.tagId,
b => b.TagId,
(a, b) => new { a, b }));
}
Conditionally expanding the query is good practice. Note that conditions like where t.IsActive == true are redundant, where t.IsActive is enough and arguable better readable with well-chosen property names (as you have).

Entity Framework/ Linq - groupby and having clause

Given the query below
public TrainingListViewModel(List<int> employeeIdList)
{
this.EmployeeOtherLeaveItemList =
CacheObjects.AllEmployeeOtherLeaves
.Where(x => x.OtherLeaveDate >= Utility.GetToday() &&
x.CancelDate.HasValue == false &&
x.OtherLeaveId == Constants.TrainingId)
.OrderBy(x => x.OtherLeaveDate)
.Select(x => new EmployeeOtherLeaveItem
{
EmployeeOtherLeave = x,
SelectedFlag = false
}).ToList();
}
I want to put in the employeeIdList into the query.
I want to retrieve all of the x.OtherLeaveDate values where the same x.OtherLeaveDate exists for each join where x.EmployeeId = (int employeeId in employeeIdList)
For example if there are EmployeeIds 1, 2, 3 in employeeIdList and in the CacheObjects.AllEmployeeOtherLeaves collection there is a date 1/1/2001 for all 3 employees, then retreive that date.
If I read you well it should be something like
var grp = this.EmployeeOtherLeaveItemList =
CacheObjects.AllEmployeeOtherLeaves
.Where(x => x.OtherLeaveDate >= Utility.GetToday()
&& x.CancelDate.HasValue == false
&& x.OtherLeaveId == Constants.TrainingId
&& employeeIdList.Contains(x.EmployeeId)) // courtesy #IronMan84
.GroupBy(x => x.OtherLeaveDate);
if (grp.Count() == 1)
{
var result = g.First().Select(x => new EmployeeOtherLeaveItem
{
EmployeeOtherLeave = x,
SelectedFlag = false
})
}
First the data is grouped by OtherLeaveDate. If the grouping results in exactly one group, the first (and only) IGrouping instance is taken (which is a list of Leave objects) and its content is projected to EmployeeOtherLeaveItems.
To the where statement add "&& employeeIdList.Contains(x.EmployeeId)"
I need to thank #IronMan84 and #GertArnold for helping me along, and I will have to admonish myself for not being clearer in the question. This is the answer I came up with. No doubt it can be improved but given no one has responded to say why I will now tick this answer.
var numberOfEmployees = employeeIdList.Count;
var grp = CacheObjects.AllEmployeeOtherLeaves.Where(
x =>
x.OtherLeaveDate >= Utility.GetToday()
&& x.CancelDate.HasValue == false
&& x.OtherLeaveId == Constants.TrainingId
&& employeeIdList.Contains(x.EmployeeId))
.GroupBy(x => x.OtherLeaveDate)
.Select(x => new { NumberOf = x.Count(), Item = x });
var list =
grp.Where(item => item.NumberOf == numberOfEmployees).Select(item => item.Item.Key).ToList();

Convert piece of code into LINQ (short syntax)

I want to convert this LINQ code
var x = from nm in names
select MyClass.SomeMethod(nm).TrimStart(',');
foreach (var vv in x)
{
// I want to group and count different types of vv here
}
to use shorter syntax, one where they do x => x in LINQ. I also want to group and count 'vv' (there could be number of similar vv's)
Well, the "dot notation" or "fluent notation" for the above is:
var x = names.Select(nm => MyClass.SomeMethod(nm).TrimStart(','));
For grouping:
var x = names.Select(nm => MyClass.SomeMethod(nm).TrimStart(','));
.GroupBy(vv => vv,
(key, group) => new { Key = key, Count = group.Count() });
Something like this?
MyClass.SomeMethod(names).TrimStart(',')
.GroupBy(x => x.vv)
.ToList()
.ForEach(x => Console.WriteLine(x.Key + ": " + x.Count()));

Resources