I have following model for posting the question and replies to the question
Model
public partial class LMS_Question
{
[Key]
public int ClassDiscussionID { get; set; }
public int? ParentClassDiscussionID { get; set; }
public string Discussion { get; set; }
public string DiscussionTitle { get; set; }
}
When user will post new question the 'ParentClassDiscussionID' will be null and if any reply added to the question then 'ClassDiscussionID' will be updated to 'ParentClassDiscussionID'.
Basically ClassDiscussionID and ParentClassDiscussionID columns have parent-child relationship.
However, I want to show the data like DiscussionTitle,ReplyCount as follows
DiscussionTitle ReplyCount
-------------------------
Question1 2 Reponses
Question2 3 Reponses
Question3 5 Reponses
So, how can I achieve this using linq to sql query ?
Thanks for the help !
First of all you need to change your model to something like this
public partial class LMS_ClassDiscussion
{
public LMS_ClassDiscussion()
{
LMS_ClassDiscussionchild = new List<LMS_ClassDiscussion>();
}
public int ClassDiscussionID { get; set; }
public int? ParentClassDiscussionID { get; set; }
public string Discussion { get; set; }
public string DiscussionTitle { get; set; }
public LMS_ClassDiscussion _LMS_ClassDiscussion { get; set; }
public List<LMS_ClassDiscussion> LMS_ClassDiscussionchild { get; set; }
}
then you need method to get all children of parents
public List<LMS_ClassDiscussion> GetChildren(IList<LMS_ClassDiscussion> source, int? parentId)
{
var children = source.Where(x => x.ParentClassDiscussionID == parentId).ToList();
//GetChildren is called recursively again for every child found
//and this process repeats until no childs are found for given node,
//in which case an empty list is returned
children.ForEach(x => x.LMS_ClassDiscussionchild = GetChildren(source, x._LMS_ClassDiscussion.ClassDiscussionID));
return children.ToList();
}
call method this way
var LMS_ClassDiscussions = GetChildren(query, null);
foreach (var item in LMS_ClassDiscussions)
{
Console.WriteLine(item._LMS_ClassDiscussion.ClassDiscussionID + "="+item.LMS_ClassDiscussionchild.Count);
}
Related
This question already has answers here:
What does Collection.Contains() use to check for existing objects?
(6 answers)
Closed 4 years ago.
In C-Sharp I have a Registrations class which basically creates a list of Questions items like this:
public partial class Registrations
{
public Registrations()
{
this.Questions = new HashSet<Questions>();
}
public int id { get; set; }
public virtual ICollection<Questions> Questions { get; set; }
}
My Questions class has a field called Title and it just gives the form field label.
public partial class Questions
{
public int id { get; set; }
public int registrationId { get; set; }
public string Title { get; set; }
public string Data { get; set; }
}
When a user creates a registration, he can add many questions with different titles. I want to check if a specific registration has a field with the title "City". I want to create a function in my Registrations class called hasCity which will return a boolean depending if the specific registration has that field.
public hasCity()
{
Questions city = new Questions();
city.Title = "City";
if( this.Questions.Contains( city ) )
{
return true;
}
return false;
}
Now, the function above always returns false and I am guessing it is because I need to create some kind of method to check only the Title attribute for the string value City.
I think you can use Any method in LinQ for this. Try the following. Hope to help, my friend:
public partial class Questions
{
public int id { get; set; }
public int registrationId { get; set; }
public string Title { get; set; }
public string Data { get; set; }
}
public partial class Registrations
{
public Registrations()
{
this.Questions = new HashSet<Questions>();
}
public int id { get; set; }
public virtual ICollection<Questions> Questions { get; set; }
public bool HasCity(string titleCity)
{
if (this.Questions.Any(x => x.Title.ToLower() == titleCity.ToLower()))
{
return true;
}
return false;
}
}
i'm trying to do some search inside some attributes of my object set but i'm getting some trouble on the right way to mount my linq query, i have my VT_Video class which has its attributes and some linked objects
public partial class VT_Video
{
public int ID { get; set; }
public string title { get; set; }
public string description { get; set; }
public virtual ICollection<VT_VideoTag> VT_VideoTag { get; set; }
}
public partial class VT_VideoTag
{
public int ID { get; set; }
public int tagID { get; set; }
public int videoID { get; set; }
public virtual VT_Tag VT_Tag { get; set; }
public virtual VT_Video VT_Video { get; set; }
}
public partial class VT_Tag
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<VT_VideoTag> VT_VideoTag { get; set; }
}
What i want to accomplish is search a user given word inside my Video collection by VT_Video.title, VT_Video.description and also by VT_Video.VT_VideoTag.VT_Tag.name, what i managed to do so far is only search the title and description:
var myVideos = db.VT_Video.Include("VT_VideoTag")
.Include("VT_VideoTag.VT_Tag")
.Where(vid =>
vid.descricao.Contains(strBusca) ||
vid.titulo.Contains(strBusca)).ToList();
Now, i know i can do what i want with some foreach and extra code but i wondered if it would be possible to do it using linq and also keep my code clean.
Thanks.
I have not worked with LINQ to SQL much, but it seems like .Any() would satisfy your requirement:
var myVideos = db.VT_Video.Include("VT_VideoTag")
.Include("VT_VideoTag.VT_Tag")
.Where(vid =>
vid.descricao.Contains(strBusca) ||
vid.titulo.Contains(strBusca) ||
vid.VT_VideoTag.Any(tag => tag.name.Contains(strBusca))).ToList();
Notice I added this clause:
vid.VT_VideoTag.Any(tag => tag.name.Contains(strBusca))
Which returns true if any tag in the collection has a name that contains your search string.
I want to return the item that has the profile ID I send. So in order to do this I will need to loop through all of the Items -> WebProproperties -> profile. The Class structure is at the end of the question.
I would rather use LINQ than create a nested foreach. I have been trying to get this to work for more than an hour now. I am stuck.
My first idea was to simply use where. But that doesn't work because you need to have something on the other side that needs to equal.
this.Accounts.items.Where(a => a.webProperties.Where(b => b.profiles.Where(c => c.id == pSearchString)) ).FirstOrDefault();
My second idea was to try using Exists which I don't have much experience with:
Item test = from item in this.Accounts.items.Exists(a => a.webProperties.Exists(b => b.profiles.Exists(c => c.id == pSearchString))) select item;
This doesn't work either:
Could not find an implementation of query pattern for source type 'Bool'
public RootObject Accounts {get; set;}
public class RootObject
{
public string kind { get; set; }
public string username { get; set; }
public int totalResults { get; set; }
public int startIndex { get; set; }
public int itemsPerPage { get; set; }
public List<Item> items { get; set; }
}
public class Profile
{
public string kind { get; set; }
public string id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class WebProperty
{
public string kind { get; set; }
public string id { get; set; }
public string name { get; set; }
public string internalWebPropertyId { get; set; }
public string level { get; set; }
public string websiteUrl { get; set; }
public List<Profile> profiles { get; set; }
}
public class Item
{
public string id { get; set; }
public string kind { get; set; }
public string name { get; set; }
public List<WebProperty> webProperties { get; set; }
}
You can use Any() to determine existence. Also, note that many of the extension methods have overloads which take a predicate, including FirstOrDefault():
this.Accounts.items.FirstOrDefault(a => a.webProperties
.Any(b => b.profiles
.Any(c => c.id == pSearchString)));
You are looking for the .Any() operation I think. This will return true/false for whether there are any items matching your query.
For example:
if (this.Accounts.Items.Any(i=>i.webProperties.Any(wp=>wp.profiles.Any(p=>p.id == MySearchId)));
EDIT: You have full answer (was posted while I was composing mine) and as pointed out in comments my answer isn't actually returning your found item, just letting you know whether there is one. You can rework the first .Any to be a .FirstOrDefault to get that match.
E.g.
var result = this.Accounts.Items.FirstOrDefault(i=>i.webProperties.Any(wp=>wp.profiles.Any(p=>p.id == MySearchId)))
You can use the below mentioned code.
var abc = rr.items.Where(p => p.webProperties.Any(c => c.profiles.Any(d => d.id == "1"))).FirstOrDefault();
Just for your reference, your class should look like:
public class RootObject
{
public string kind { get; set; }
public string username { get; set; }
public int totalResults { get; set; }
public int startIndex { get; set; }
public int itemsPerPage { get; set; }
private List<Item> _items=new List<Item>();
public List<Item> items
{
get { return _items; }
set { _items = value; }
}
}
I'm looking for a help.
I'm working an exercise based on MVC.
My model contains 2 classes. The DVD and the Category
public class DVD
{
public int ID
{ get; set; }
public string Title
{ get; set; }
public decimal Price
{ get; set; }
public int Quantity
{ get; set; }
public int Duration
{ get; set; }
public string Image
{ get; set; }
public virtual IList<Category> Categories_List
{ get; set; }}
Now the Category which is a method contains the following
public class Category
{
public int Id
{ get; set; }
public string Title
{ get; set; }
public virtual IList<DVD> DVDs
{ get; set; } }
Both DVD and Category are under the Model folder.
What I want to do is to create a list in my controller of the Category (inside the method of public ActionResult Details(int id = 0) )
to collect all the dvds which are in the category with the id 1 for example.
I found something simillar but I have problem when I have to check if the DVD's category id is the same with the one I'm looking for.
Search list of object based on another list of object c#
Can anyone help me to do it?
Thank you
Use LINQ Where. This will return call of the movies that match a particular category:
var moviesMatchingCategory = _masterMovieList.Where(ml => ml.Categories_List.Any(cl => cl.Id == categoryIdToCompare)).ToList();
If you can use linq this will help:
public IEnumerable<DVD> FindDvdByCategoryId(int categoryId, IEnumerable<DVD> dvdEnumerable)
{
return dvdEnumerable.Where(dvd => dvd.Categories_List.Any(c => c.Id == categoryId)).ToList();
}
List<DVD> list = dvds.Where(x=>x.Categories_List.Contains(y=>y.Id==Id)).ToList();
Try the above.
I have a Model like this
public class Challenge
{
public int ID { get; set; }
public string Name { get; set; }
public string Blurb { get; set; }
public int Points { get; set; }
public string Category { get; set; }
public string Flag { get; set; }
public List<string> SolvedBy { get; set; }
}
public class ChallengeDBContext : DbContext
{
public DbSet<Challenge> Challenges { get; set; }
}
and then Controller like this. But I cannot update the List "SolvedBy", the next time I step through with the debugger, the list is still empty.
[HttpPost]
public string Index(string flag = "", int id=0)
{
Challenge challenge = db.Challenges.Find(id);
if (flag == challenge.Flag)
{
var chall = db.Challenges.Find(id);
if (chall.SolvedBy == null)
{
chall.SolvedBy = new List<string>();
}
chall.SolvedBy.Add(User.Identity.Name);
db.Entry(chall).State = EntityState.Modified;
db.SaveChanges();
//congrats, you solved the puzzle
return "got it";
}
else
{
return "fail";
}
}
is there any way around it to make a list of strings kept in the database?
EF don't know how to store an array in database table so it just ignore it. You can create another table/entity or use XML/JSON to store the list. You can serialize the list before saving and deserialize it after loading from database
A List<T> in a model would normally map to a second table, but in your DbContext you only have a single table. Try adding a second table.
public class ChallengeDBContext : DbContext
{
public DbSet<Challenge> Challenges { get; set; }
public DbSet<Solution> Solutions {get; set;}
}
public class Challenge
{
public int ID { get; set; }
public string Name { get; set; }
public string Blurb { get; set; }
public int Points { get; set; }
public string Category { get; set; }
public string Flag { get; set; }
public List<Solution> SolvedBy { get; set; }
}
public class Solution
{
public int ID { get; set; }
public string Name { get; set; }
}
Then your controller can use code along the lines of...
var chall = db.Challenges.Find(id);
if (chall.SolvedBy == null)
{
chall.SolvedBy = new List<Solution>();
}
chall.SolvedBy.Add(new Solution {Name=User.Identity.Name});
None of the above has been tested and I may have made some mistakes there, but the general principle I want to illustrate is the fact that you need another table. The List<T> represents a JOIN in SQL.