Getting properties from a child - c#

I have the following entities:
public class Parent
{
int Id { get; set; }
string ParentName { get; set; }
List<Child> Children { get; set; }
}
public class Child
{
int Id { get; set; }
string ChildName { get; set; }
}
and the following dto:
public class ParentDTO
{
int Id { get; set; }
List<string> ChildrenNames { get; set; }
}
using QueryOver code below I can get the Parent values
ParentDTO result = null;
Parent parentAlias = null;
Child childAlias = null;
var query = session.QueryOver(() => parentAlias)
.JoinAlias(() => parentAlias.Children, () => childAlias, JoinType.LeftOuterJoin)
.SelectList(list => list.Select(c => c.Id).WithAlias(() => result.Id)
.Select(c => c.ParentName).WithAlias(() => result.Name)
//this part does not work
.Select(c => c.Children .Select(v => v.ChildName)).WithAlias(() => result.ChildrenNames)
//
)
.TransformUsing(Transformers.AliasToBean<ParentDTO>());
return query.List<ParentDTO>();
However I cant seem to be able to project the list of childName values into my ChildrenNames collection.
Any ideas?

As some guys said in comments, you need to do two queries. Using linq, you could try something like this:
// get the parent Ids
var parentIds = session.Query<Parent>().Select(c => c.Id).ToList();
// get the childNames
var childNames = session.Query<Child>()
.Where(x => parentIds.Contains(x.ParentId)) // get on the child from parents query
.Select(x => new {x.Name, x.ParentId}) // get only the properties you need
.ToList(); // list of anon objects
// loop in memory between parentIds filling the corresponding childNames
var result = parentIds.Select(parentId => new ParentDTO()
{
Id = parentId,
ChildrenNames = childNames.Where(x => x.ParentId == parentId).ToList()
}).ToList();
I am not sure if it works, but you could try this in a single query:
var query = from p in session.Query<Parent>()
let names = p.Children.Select(c => c.ChildName).ToList()
select new ParentDTO()
{
Id = o.Id,
ChildrenNames = names
};
return query.Tolist();
Obs: I did not test it.

Related

How can I select using LINQ for an entry that contains a LIST with more than one row?

I have a List of IJapaneseDictionaryEntry objects:
public interface IJapaneseDictionaryEntry
{
int Sequence { get; }
IEnumerable<IKanji> Kanjis { get; }
IEnumerable<IReading> Readings { get; }
IEnumerable<ISense> Senses { get; }
}
public interface IKanji
{
string Text { get; }
IEnumerable<KanjiInformation> Informations { get; }
IEnumerable<Priority> Priorities { get; }
}
Which I am do a LINQ query on like this:
var a = entries.SelectMany(x => x.Kanjis)
.Select(x => new { x.Text, x.Priorities });
Is there a way that I can filter this so I only retrieve entries that have at least one priority?
You can use Eumerable.Where:
var a = entries.SelectMany(x => x.Kanjis)
.Where(x => x.Priorities.Any())
.Select(x => new { x.Text, x.Priorities });
Or in query syntax:
var e =
from entry in entries
from kanji in entry.Kanjis
where kanji.Priorities.Any()
select new { kanji.Text, kanji.Priorities };

LINQ GroupBy return dictionary with given objects as value

I have an IEnumerable<ValueObj> object with multiple valid ValueObj objects in it. I would like to group those objects by Id and receive Dictionary<Guid, IEnumerable<ValueObj>> where the Key is Id from ValueObj, and Value is just unchanged ValueObj.
public class ValueObj
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime Time { get; set; }
public double Result { get; set; }
}
I've tried to mess with Linq GroupBy but with no success
IEnumerable<ValueObj> persons = ...;
var results = persons.GroupBy(
p => p.Id,
p => p,
(key, g) => new { PersonId = key, Cars = g.ToList() });
Try this:
IEnumerable<ValueObj> col = ...;
var dict = col.GroupBy(x => x.Id).ToDictionary(x => x.Key, x => x.ToList());

Selecting specific columns from GroupBy list

Model:
public class Ticket {
public Ticket();
public int Id { get; set; }
public virtual TicketUrgency TicketUrgency { get; set; }
public int UrgencyId { get; set; }
}
public class TicketUrgency {
public TicketUrgency();
[Key]
public int Id { get; set; }
[MaxLength(50)]
[Required]
public string Name { get; set; }
public ICollection<Ticket> Tickets { get; set; }
}
I have the following linq statement:
var model = Entities
.Include(x => x.TicketUrgency)
.GroupBy(x => x.UrgencyId)
.Select(g => new {
id = g.Key,
count = g.Count(),
name = g.FirstOrDefault(u => u.UrgencyId == g.Key).TicketUrgency.Name
});
I want to Group Entities by UrgencyId and then return the Key (UrgencyId), and also count of the items in a single group and show the name of the Urgency.
When I run it, the query just gets hung up without any exceptions.
This should work, doing it the other way around, by retrieving all TicketUrgencies first and grouping it.
Entities.Include(e => e.Tickets)
.GroupBy(t => t.Id)
.Select(g => new {
id = g.Key,
name = g.FirstOrDefault().Name,
count = g.FirstOrDefault().Tickets.Count()
});
Very simple. Just try this :
var model = Entities
.Include(x => x.TicketUrgency)
.GroupBy(x => new {UrgencyId = x.UrgencyId ,
Name = x.TicketUrgency.Name})
.Select(x=> new { UrgencyId = x.Key.UrgencyId,
Name = x.Key.Name,
Count = x.Count()});
Since you are grouping by UrgencyId, you know all members of g have the same id as the Key, so to pick up the name just pull the first one. You also know g isn't empty because that wouldn't make a group:
var model = Entities
.Include(x => x.TicketUrgency)
.GroupBy(x => x.UrgencyId)
.Select(g => new {
id = g.Key,
name = g.First().TicketUrgency.Name
count = g.Count(),
});
You could group by those two properties:
var model = Entities
.Include(x => x.TicketUrgency)
.GroupBy(x => new{ x.UrgencyId, x.TicketUrgency.Name })
.Select(g => new {
id = g.Key.UrgencyId,
count = g.Count(),
name = g.Key.Name
});
Another way could be, as #ASpirin suggested,starting the query from TickerUrgency:
var result= TicketUrgencies.Include(t=>t.Tickets)
.Where(t=>t.Tickets.Any())
.Select(t=> new {id=t.Id,name=t.Name, count= t.Tickets.Count()})

Add GroupBy to Select

I have this query
[HttpGet]
public List<AttachedPhotosModel> GetReportAttachedPhotos(int reportId)
{
var photos = new ReportsRepository().GetInjuryPhotos(reportId);
return photos.Select(x => new AttachedPhotosModel()
{
Id = x.Id,
Type = x.InjuryType,
Photos = photos.Where(y => y.InjuryType == x.InjuryType).Select(z => z.ServicePhotoUrl).ToList()
}).ToList();
}
I need to GroupBy InjuryType, how to do this?
I added return photos.GroupBy(k => k.InjuryType).Select(x => new AttachedPhotosModel() but how to select model, x have new value key and I don't know how to select my data
This code should work. Assuming photos is collection of objects with InjuryType property and PhotoUrl property and AttachedPhotosModel has an InjuryType and Photos properties like this.
public class AttachedPhotosModel
{
public string InjuryType { set; get; }
public List<string> Photos { set; get; }
}
Code for grouping by InjurType.
var grouped = photos
.GroupBy(s => s.InjuryType,d => d.PhotoUrl, (k, g) => new
AttachedPhotosModel
{
InjuryType = k,
Photos = g.ToList()
}).ToList();

Linq How to perform Subquery with max function that returns a primitive value such as an integer?

I have the below query. :
List<MyItem> myList
= randomEntity
.GroupBy(x => new {
x.Id,
x.randomInnerEntity.Name,
x.randomInnerEntity.Number
})
.Select(z => new MyItem
{
Id = z.Key.Id,
Name = z.Key.Name,
Totals = z.Count(),
LatestObj = randomEntity.Where(x => x.Id == z.Key.Id)
.GroupBy(x => x.Id)
.Select(gr => new {
item1 = gr.Key,
item2 = gr.Max(x => x.SomeInteger.Value)
})
})
.OrderBy(z => z.Name)
.ToList();
As you can see the inner subquery, that provides a dynamic object of LatestObj works but it provides an anonymous object. I was wondering how to perform the same query but return a primitive type like integer.
***As requested
public class MyItem
{
property Guid? Id { get; set; }
property String Name { get; set; }
property Int MaxValueTryingToGet { get; set; } //This is the field I would like to set with the integer max
property Int Totals { get; set; }
property dynamic LatestObj { get; set; }
property randInner randomInnerEntity { get; set; }
}
LatestObj = randomEntity.Where(x => x.Id == z.Key.Id)
.GroupBy(x => x.Id)
.Select(gr => new {
item1 = gr.Key,
item2 = gr.Max(x => x.SomeInteger.Value)
})
Since you are just selecting items where the item id matches z.Key.Id, there does not seem to be much point grouping by id.
You can should be able to get the maximum value directly by using
LatestObj = randomEntity.Where(x => x.Id == z.Key.Id).Max(x -> x.SomeInteger.Value)

Categories

Resources