Currently I have 2 database tables which looks like:
--------------- --------------------
| Categories | | Item_Categorys |
--------------- --------------------
| id | | id |
| Title | | Category_ID |
--------------- | Item_ID |
--------------------
I have a Model which displays Checkboxes on my View which is like
LocalCategoryModel
-------------------
int categoryid
string category_title
bool ischecked
I'm trying to get all the items categorys from the table and then get all the category rows then crosscheck them to where if there's a category item, it Puts it in a IEnumerable. So at the end, the LocalCategory has all the categories and then the ischecked is set to true or false depending on if it has a row in the Item_Categorys sql table.
public class LocalCategoryModel
{
public int categoryid { get; set; }
public string category_title { get; set; }
public bool ischecked { get; set; }
}
public IEnumerable<LocalCategoryModel> getSourec()
{
IEnumerable<LocalCategoryModel> query = from tbcat in Categories
join tbitem_cat in dc.Item_Categorys
on tbcat.id equals tbitem_cat.Category_ID into ct
from tbitem_cat in ct.DefaultIfEmpty()
select new LocalCategoryModel
{
categoryid = tbcat.id,
category_title = tbcat.Title,
ischecked = tbitem_cat == null ? false : true
};
return query;
}
I'll get you some example.
It helps you.
I refer to a book named 'C# 4.0 IN A NUTSHELL'.
// outer collection
customers.Join (
purchases, // inner collection
c => c.ID, // outer key selector
p => p.CustomerID, // inner key selector
(c, p) => new { c, p } ) // result selector
.OrderBy (x => x.p.Price)
.Select (x => x.c.Name + " bought a " + x.p.Description);
from c in customers
join p in purchases on c.ID equals p.CustomerID
select new { c.Name, p.Description, p.Price };
class Category { public int id; public string Title; };
class CategoryItem { public int category_id; public int item_id; }
class Category { public int id; public string title; };
// Create categories list
var categories = new List<Category>() { new Category { id = 1, title = "First" }, new Category { id = 2, title = "Second" } };
// Create categories items list
var categories_items = new List<CategoryItem>() { new CategoryItem { category_id = 1, item_id = 2 } };
// All categories in categories_items
var categories_items_set = categories_items.Select(x => x.category_id).Distinct();
// Final query
var q = categories.Select(x => new { categoryid = x.id, category_title = x.title, ischecked = categories_items_set.Contains(x.id) });
q.ToList()
// output
categoryid = 1, category_title = First, ischecked = True
categoryid = 2, category_title = Second, ischecked = False
Related
I need to call a method FormatCourseTitle() from linq query but receive error message "Linq to Entity does not recognize the method FormatCourseTitle..." How to solve this problem?
public ActionResult Index()
{
var searchResults = (from a in db.Courses
join b in db.Summary on
new { subject = a.subject, catalog = a.catalog, coursetitle = FormatCourseTitle(a.coursetitle) } equals
new { subject = b.Subject, catalog = b.Catalogno, coursetitle = b.CourseTitle } into ab
from b in ab.DefaultIfEmpty()
where a.Active == true
select new JoinModel
{
Courses = a,
Summary2020 = b
} ).ToList();
return View(searResults);
}
public class JoinModel
{
[Key]
public int Id { get; set; }
public Courselist Courses { get; set; }
public Contentsummary Summary { get; set; }
}
public string FormatCourseTitle(string courseTitle)
{
//find if last three characters are " or"
string[] words = courseTitle.Trim().ToLower().Split(' ');
int j = words.Count();
string tempStr = string.Empty;
if (words[j] == "or")
{
tempStr = courseTitle.Substring(0, courseTitle.Length - 3);
}
else
{
tempStr = courseTitle;
}
return tempStr;
}
You should use extension method as
public static class StringHelper
{
public static string FormatCourseTitle(this string courseTitle)
{
//find if last three characters are " or"
string[] words = courseTitle.Trim().ToLower().Split(' ');
int j = words.Count();
string tempStr = string.Empty;
if (words[j] == "or")
{
tempStr = courseTitle.Substring(0, courseTitle.Length - 3);
}
else
{
tempStr = courseTitle;
}
return tempStr;
}
}
Change query to
var searchResults = (from a in db.Courses
join b in db.Summary on
new { subject = a.subject, catalog = a.catalog, coursetitle = a.coursetitle.FormatCourseTitle() } equals
new { subject = b.Subject, catalog = b.Catalogno, coursetitle = b.CourseTitle } into ab
from b in ab.DefaultIfEmpty()
where a.Active == true
select new JoinModel
{
Courses = a,
Summary2020 = b
} ).ToList();
I find a way to add condition in linq query to solve this problem.
var searchResults = (from a in db.Courses
join b in db.Summary on
new { subject = a.subject, catalog = a.catalog, coursetitle = a.coursetitle.Trim().EndsWith(" or")?a.coursetitle.Substring(0,a.coursetitle.Length-3):a.coursetitle } equals
new { subject = b.Subject, catalog = b.Catalogno, coursetitle = b.CourseTitle } into ab
from b in ab.DefaultIfEmpty()
where a.Active == true
select new JoinModel
{
Courses = a,
Summary2020 = b
} ).ToList();
What is the most efficient way to
a) retrieve all children objects from multiple parent types, and
b) know what the parent type is and the exact parent Id for each child?
Currently this is what I'm doing and it's incredibly inefficient, at least the part where I find the specific parent of each child.
public class ChildModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ParentType1Model
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ChildModel> Children { get; set; }
}
public class ParentType2Model
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ChildModel> Children { get; set; }
}
//Get all ChildModels from ParentType1
var parentType1Children = db.ParentType1Models
.SelectMany(x => x.Children)
.ToList();
listOfChildModels.AddRange(parentType1Children);
//Get all ChildModels from ParentType2
var parentType2Children = db.ParentType2Models
.SelectMany(x => x.Children)
.ToList();
listOfChildModels.AddRange(parentType2Children);
//Find the parent for each ChildModel
foreach (var child in listOfChildModels)
{
ParentType1Model parentType1ModelCheck = null;
ParentType2Model parentType2ModelCheck = null;
parentType1ModelCheck = await db.ParentType1Models
.Where(p => p.Children
.Any(i => i.Id == child.Id))
.FirstOrDefaultAsync();
//If first check is null, then move to second check
if (taskProjectModelCheck == null)
{
parentType2ModelCheck = await db.ParentType2Models
.Where(p => p.Children
.Any(i => i.Id == child.Id))
.FirstOrDefaultAsync();
}
//Now record the parent type and parent Id in an object containing the original ChildModel and it's parent's info (to be used later for various things)
ChildViewModel childViewModel = new ChildViewModel();
childViewModel.ChildModel = child;
if (parentType1ModelCheck != null)
{
childViewModel.ParentType = "ParentType1";
childViewModel.ParentModelId = parentType1ModelCheck.Id;
}
else if (parentType2ModelCheck != null)
{
childViewModel.ParentType = "ParentType2";
childViewModel.ParentModelId = parentType2ModelCheck.Id;
}
}
How about something like this?
var ids1 = from p in db.ParentType1Models
from c in p.Children
select new
{
parentId = p.Id,
parentName = p.Name,
childName = c.Name,
childId = c.Id,
ParentType = "One"
};
var ids2 = from p in db.ParentType2Models
from c in p.Children
select new
{
parentId = p.Id,
parentName = p.Name,
childName = c.Name,
childId = c.Id,
ParentType = "Two"
};
var results = ids1.Union(ids2).ToList();
I ended up using raw SQL, and it is extremely fast.
By writing a query directly against the database, I was able to go straight to the many to many relationship tables that get created by Entity Framework when I set up the ParentTypeXModels and ChildModels.
result = dbContext.Database.SqlQuery<ANewChildObject>(
"select
ParentModelId = pm.Id,
Id = c.Id,
ParentType = 'ParentType1'
from dbo.ChildModels c
JOIN dbo.ParentType1ModelsChildModels pmT ON c.Id = pmT.ChildModel_Id
JOIN dbo.ParentType1Models pm on pmT.ParentType1Model_Id = pm.Id
UNION ALL
select
ParentModelId = pm.Id,
Id = c.Id,
ParentType = 'ParentType2'
from dbo.ChildModels c
JOIN dbo.ParentType2ModelsChildModels pmT ON c.Id = pmT.ChildModel_Id
JOIN dbo.ParentType2Models pm on pmT.ParentType2Model_Id = pm.Id"
).ToList();
I need to convert:
SELECT Author.AuthorName, Author.AuthorSurname , Category.CategoryName, COUNT(Record.IdCategory) AS Ilosc
FROM ((Record
INNER JOIN Author ON Author.Id = Record.IdAuthor)
INNER JOIN Category ON Category.Id = Record.IdCategory)
GROUP BY AuthorName, AuthorSurname, CategoryName
Order by Ilosc ASC
To lambda.
I have created
public class SortModel
{
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Kategoria { get; set; }
}
For now i wrote this code but i need to add .groupby:
public List<SortModel> GetAuthorCategories()
{
var context = new KolekcjaPlytEntities2();
List<SortModel> queryAllCustomers = context.Record
.Join( context.Author, r => r.IdAuthor, a => a.Id, (r, a) => new {r, a})
.Join(context.Category, c => c.r.IdCategory, cn => cn.Id, (c, cn) => new SortModel()
{
Imie = c.a.AuthorName,
Nazwisko = c.a.AuthorSurname,
Kategoria = cn.CategoryName,
})
.ToList();
return queryAllCustomers;
}
Thanks.
You could use LINQ query expression like this one.
List<SortModel> queryAllCustomers = (from r in context.Record
join a in context.Author on r.IdAuthor equals a.Id
join c in context.Category on r.IdCategory equals c.Id
group new {a, c} by new {a.AuthorName, a.AuthorSurname , c.CategoryName} into gruopAC
let countCategory= gruopAC.Count()
orderby countCategory
select new SortModel
{
Imie=gruopAC.Key.AuthorName,
Nazwisko =gruopAC.Key.AuthorSurname ,
Kategoria =gruopAC.Key.CategoryName,
Ilosc=countCategory}).ToList()
Suppose you have
public class SortModel
{
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Kategoria { get; set; }
public int Ilosc { get; set; }
}
You can try this code:
public List<SortModel> GetAuthorCategories()
{
var context = new KolekcjaPlytEntities2();
List<SortModel> queryAllCustomers = context.Record
.Join(context.Author, r => r.IdAuthor, a => a.Id, (r, a) => new {r, a})
.Join(context.Category, ar => ar.r.IdCategory, c => c.Id, (ar, c) => new {
r = ar.r,
a = ar.a,
c = c
})
// Here you have a IEnumerable<dynamic> of items { a = Author, c = Category, r = Record }
// All items with same { a.Id, c.Id } are grouped
.GroupBy(x => new { x.a.Id, x.c.Id }, (x, items) => new SortModel()
{
// First() cannot return null, we have inner join everywhere
Imie = items.First().a.AuthorName,
Nazwisko = items.First().a.AuthorSurname,
Kategoria = items.First().c.CategoryName,
Ilosc = items.Count()
})
.ToList();
return queryAllCustomers;
}
Here i have a problem with data table to convert json. This is my class called SearchCollection
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public int ClassGroupId { get; set; }
public string ClassName { get; set; }
public int ClassNumber { get; set; }
public int BookTypeId { get; set; }
public string BookType { get; set; }
I have collected a data from store procedure and pushed into the datatable, thats why am using ConvertToDatatable(), that time i got a datatable which contains 3 tables data
static DataTable ConvertToDatatable(IEnumerable<SearchCollection> list)
{
var dt = new DataTable();
dt.Columns.Add("CategoryId");
dt.Columns.Add("CategoryName");
dt.Columns.Add("ClassGroupId");
dt.Columns.Add("ClassName");
dt.Columns.Add("ClassNumber");
dt.Columns.Add("BookTypeId");
dt.Columns.Add("BookType");
foreach (var item in list)
{
var row = dt.NewRow();
row["CategoryId"] = item.CategoryId;
row["CategoryName"] = item.CategoryName;
row["ClassGroupId"] = item.ClassGroupId;
row["ClassName"] = item.ClassName;
row["ClassNumber"] = item.ClassNumber;
row["BookTypeId"] = item.BookTypeId;
row["BookType"] = item.BookType;
dt.Rows.Add(row);
}
return dt;
}
this contain 3 tables data.
So.. this is have tried to group the data, but here am getting the answer like category on top inside category shows booktype and inside booktype shows list of classnames, but i want 3 set of data
category {},booktype{},classnames{}
var result = rows.GroupBy(r => new { x = r["CategoryId"], y = r["CategoryName"] }).Select(g => new
{
CategoryId = g.Key.x,
CategoryName = g.Key.y,
BookTypes = g.GroupBy(r => new { h = r["BookTypeId"], i = r["BookType"] }).Select(g1 => new
{
BookTypeId = g1.Key.h,
BookType = g1.Key.i,
ClassNames = g1.Select(r => new
{
ClassGroupId = r["ClassGroupId"],
ClassName = r["ClassName"],
ClassNumber = r["ClassNumber"]
}),
}),
});
Rusult
This is my result
{ CategoryId:1 CategoryName:CD ClassGroupId:15 ClassName:I ClassNumber:1 BookTypeId:1 BookType:General CD}
{ CategoryId:2 CategoryName:DVD ClassGroupId:16 ClassName:II ClassNumber:2 BookTypeId:2 BookType:General DVD}
{ CategoryId:3 CategoryName:Book ClassGroupId:17 ClassName:III ClassNumber:3 BookTypeId:3 BookType:General Books}
But i want the result like this
+ Category={ CategoryId:1 CategoryName:CD
CategoryId:2 CategoryName:DVD
CategoryId:3 CategoryName:Book }
ClassGroup={ClassGroupId:15 ClassName:I ClassNumber:1
ClassGroupId:16 ClassName:II ClassNumber:2
ClassGroupId:17 ClassName:III ClassNumber:3}
BookType{ BookTypeId:1 BookType:General CD
BookTypeId:2 BookType:General DVD
BookTypeId:3 BookType:General Books
}
here my result is booktype is under category and classname under booktype. but i want the result just like 3 groups of records in single json, any one help just like category grouped collection, class grouped collection and book type collection in single json data.
Is this what you're looking for?
var result = new
{
Category = rows
.GroupBy(r => new
{
x = r["CategoryId"],
y = r["CategoryName"]
})
.Select(g => new
{
CategoryId = g.Key.x,
CategoryName = g.Key.y
}),
ClassGroup = rows
.GroupBy(r => new
{
x = r["ClassGroupId"],
y = r["ClassName"],
z = r["ClassNumber"]
})
.Select(g => new
{
ClassGroupId = g.Key.x,
ClassName = g.Key.y,
ClassNumber = g.Key.z
}),
BookType = rows
.GroupBy(r => new
{
x = r["BookTypeId"],
y = r["BookType"]
})
.Select(g => new
{
BookTypeId = g.Key.x,
BookType = g.Key.y
})
};
Fiddle: https://dotnetfiddle.net/h9qXqc
I am trying to construct a navigation menu using a Categories table from my db.
I have a similar layout as below in Categories table.
public List<Category> CategoryData = new List(new Category[] {
new Category{ CategoryId = 1, Name = "Fruit", ParentCategoryId = null},
new Category{ CategoryId = 2, Name = "Vegetables", ParentCategoryId = null},
new Category{ CategoryId = 3, Name = "Apples", ParentCategoryId = 1},
new Category{ CategoryId = 4, Name = "Bananas", ParentCategoryId = 1},
new Category{ CategoryId = 5, Name = "Cucumber", ParentCategoryId = 2},
new Category{ CategoryId = 6, Name = "Onions", ParentCategoryId = 2}
); }
The above should return something like
Fruit (parent)
"===Apples, Bananas (child)
Vegetables (parent)
"===Cucumber, Onions (child)
I need to be able to pass this as some kind of 'grouped' (grouped by parentid) collection to my View.
How to do this?
It would seem like this is a good example of when translating your model to a viewModel would come in handy. As you could create a collection of CategoryViewModel which have a Childrens property of CategoryViewModel using the same technique describe by #thomas.
public class CategoryViewModel
{
public int CategoryId { set; get; }
public string CategoryName { set; get; }
public int? ParentCategoryId { set; get; }
public IEnumerable<CategoryViewModel> Children { set; set; }
}
public static IEnumerable<CategoryViewModel> GetAllCategoryViewModel(IList<Category> categories)
{
var query = GetChildren(null, categories);
return query.ToList();
}
public static IEnumerable<CategoryViewModel> GetChildren(int? parentId, IList<Category> categories)
{
var children = from category in categories
where category.ParentCategoryId == parentId
select
new CategoryViewModel
{
CategoryId = category.CategoryId,
CategoryName = category.CategoryName,
ParentCategoryId = category.ParentCategoryId,
Children = GetChildren(category.CategoryId, categories)
};
return children;
}
How about something like:
private void Test()
{
var categoryData = new List
{
new Category {CategoryId = 1, Name = "Fruit", ParentCategoryId = null},
new Category {CategoryId = 2, Name = "Vegetables", ParentCategoryId = null},
new Category {CategoryId = 3, Name = "Apples", ParentCategoryId = 1},
new Category {CategoryId = 4, Name = "Bananas", ParentCategoryId = 1},
new Category {CategoryId = 5, Name = "Cucumber", ParentCategoryId = 2},
new Category {CategoryId = 6, Name = "Onions", ParentCategoryId = 2}
};
var query = from category in categoryData
where category.ParentCategoryId == null
select category;
foreach ( var item in query )
{
Debug.WriteLine( string.Format( "{0} (parent)", item.Name ) );
Debug.WriteLine( GetChildren(item.CategoryId, categoryData ) );
}
}
private static string GetChildren( int parentCategoryId, IEnumerable categoryData)
{
var children = ( from category in categoryData
where category.ParentCategoryId == parentCategoryId
select category.Name ).ToArray();
return string.Format( "==={0} (child)", string.Join( ", ", children ) );
}
var list = from a in CategoryData
join b in CategoryData on a.ParentCategoryId equals b.CategoryId into c
from d in c.DefaultIfEmpty()
where d != null
select new {
a.CategoryId,
a.Name,
a.ParentCategoryId,
ParentName = d.Name
};
returns
CategoryId Name ParentCategoryId ParentName
3 Apples 1 Fruit
4 Bananas 1 Fruit
5 Cucumber 2 Vegetables
6 Onions 2 Vegetables
You can then loop through it in your view and format accordingly.