How do you query the database within the model? - c#

NOTE: This is an entire rewrite of the previous question.
I have a model.
class Paragraph
{
public int Id { get; set; }
public int SectionId { get; set; }
public virtual Section Section { get; set; }
public int Major { get; set; }
public int Option { get; set; }
public ICollection<Paragraph> Options
{
get
{
// What I'm trying to return is:
//
// Section.Paragraphs
// .Where(p => p.Major == Major && p.Option != Option)
// .ToList()
}
}
}
It is involved in a one to many relationship; where each Section has many Paragraphs. What I'm trying to return is a list of paragraphs where their Major is the same as the entity's Major and the Option isn't the same. Basically.
Where(p => p.Major == Major && p.Option != Option)
Any advice on how to accomplish this? Thank you.

You want your Section property to be non-null. Presumably you have a Section class that has a property of type List<Paragraph> or the like, since you describe this situation as one model "belonging" to another.
If you are thinking that just because your paragraph is contained in a section, you will get some sort of reciprocity for free, you are mistaken. You will have to see to maintaining this relationship yourself.

I solved it. Woop-woop! All I did was check if Section was null, and if it was I returned a blank List<Paragraph>. So Options becomes.
public ICollection<Paragraph> Options
{
get
{
if (Section != null)
{
return Section.Paragraphs
.Where(p => p.Major == Major && p.Option != Option)
.ToList();
}
else
{
return new List<Paragraph>();
}
}
}

Related

Fluent validation to compare properties from two list

I'm working lots of complicated Validation Rules. We are using Fluent Validation to help with this and its a wonderful tool. I have a class which contains two list of same type.
public class BookingDto
{
public IEnumerable<Trip> OutTripDetails { get; set; }
public IEnumerable<Trip> InTripDetails{ get; set; }
}
public class Trip
{
public DateTime? TravelDate { get; set; }
public IEnumerable<ClassTst> Stops { get; set; }
}
if (OutTripDetails .TravelDate != null && InTripDetails.TravelDate != null)
{
if (InTripDetails.TravelDate < (DateTime)OutTripDetails .TravelDate)
{
Console.Writeline("Error here with date");
}
}
I want to convert the above validation to use fluentvalidation
RuleForEach(m => m.BookingDto.OutTripDetails )
.ChildRules(r => r.RuleFor(t => t.TravelDate )
// .GreaterThanOrEqualTo(r => r.)
//RuleForEach(m => m.BookingDto.InTripDetails)
.ChildRules(r => r.RuleFor(t => t.TravelDate )
Can I achieve this validation check with fluentvalidation in c#? I hav tried to implemnet with when condition to check if it is null but i couldnt make it work, Can someone hlp me to do this.

How to include virtual ICollection and also specific item from this collection in EF core?

I'm trying to load all properties of my Entity, but two of them are virtual. So I have to include them in query. The problem is that the second virtual property is single item from the first one.
Example: Let's suppose that I have Entity Magazine with all its Issues and CurrentIssue (from this moth). And I want to load everything.
public class Magazine
{
public int Id { get; set; }
public string Name { get; set; }
...
public virtual ICollection<Issue> Issues { get; set; }
public virtual Issue CurrentIssueOn
{
get
{
if (Issues != null)
{
var date = DateTime.Now;
if (date.AddDays(DaysSendBack) > DateTime.Now.Date)
{
date = date.AddDays(DaysSendBack);
}
return Issues
.Where(i => (i.IssueDate.HasValue && i.IssueDate.Value >= date))
.OrderBy(i => i.IssueDate)
.FirstOrDefault();
}
return null;
}
}
And I have tried this:
public IQueryable<MagazineListViewModel> GetList(string userAuthToken)
{
return mapper.ProjectTo<MagazineListViewModel>(dbContext
.Magazine
.Include(m => m.Issues)
.Include(m => m.CurrentIssueOn)
.AsNoTracking()
.AsQueryable());
}
But the CurrentIssueOn is always null, because during query execution the Issues collection is still null.
I think, that if I remove the virtual keyword from Issues collection then It will work in this case. But I have another queries, where I dont want to include Issues, so its not good solution.
I'm not sure what's going on here, but your entity should probably look like this:
public virtual ICollection<Issue> Issues { get } = new HashSet<Issue>();
[NotMapped]
public virtual Issue CurrentIssueOn
{
There's no reason to start with your Navigation Property collections being null. Just initialize them to empty collections.

C# Web API DTO combining two Objects in MVC

Hi I'm a newbie to C# and DTO's and I'm looking for a bit of advice in writing a method. Basically I have two transfer objects, Members and Source. What I'm trying to achieve is display a list of Members from a specific Source.
The only problem is I need to be able to display Members associated with a SourceId from a SourceRef. As I dont want to pass the sensitive MemberID and SourceId so each has a reference id and thats how I will be identifying them in my API
Member Object
public class MemberObj
{
public int memId { get; set; }
public String memRef { get; set; }
public String fName { get; set; }
public String lName { get; set; }
public String email { get; set; }
public String detail { get; set; }
public int sourceId { get; set; }
}
Source Object
public class SourceObj
{
public int sourceId { get; set; }
public String sourceRef { get; set; }
}
So I would like to go to the address for example
http://..../api/Member/Source/{sourceRef}
and display the list of Members associated to the sourceId via the sourceRef
I came up with something along these lines....
public IEnumerable<MemberObj> GetMem(String code)
{
var sc = db.Sources;
var thisSrc = sc.Where(s => s.sourceRef == code).SingleOrDefault();
return db.Members.Select(s => new MemberObj
{
memId = s.memId,
firstName = s.firstName,
lastName = s.lastName,
email = s.emailAddress,
memRef = s.memRef
}).AsEnumerable().Where(s => s.sourceRef== thisSrc.sourceRef);
But this returns nothing.
The following accepts code as the sourceRef and returns the SourceID that the ref corresponds too.
From here, it simply filters all members to only the ones with the matching sourceID. (I don't have a copy of VS near me so the syntax may be out! If only Notepad++ had intelisense...)
public IEnumerable<MemberObj> GetMem(String code)
{
int soureID = db.Sources.Where(s => s.sourceRef == code).SingleOrDefault().sourceID; //I'm assuming code is the source ref??
//Insert and handle your sourceID == 0 checks here.
//...
return db.Members.Where(m => m.sourceId == sourceID);
}
This should work:
public IEnumerable<MemberObj> GetMem(String code)
{
var thisSrc = db.Sources
.Where(s => s.sourceRef == code)
.SingleOrDefault();
if(thisSrc == null)
return Enumerable.Empty<MemberObj>();
return db.Members.Where(m => m.sourceId == thisSrc.sourceId);
}
Take in account, that you should handle the case when there are more than one source by given code (SingleOrDefault throws an exception in that case.)
If you are sure that is not a case use FirstOrDefault instead.
Just building into Hamlet's answer, you could do something like this to return a DTO instead of your Member Entity:
public IEnumerable<MemberDTO> GetMem(String code)
{
//Get the source object by sourceRef
var thisSrc = db.Sources
.Where(s => s.sourceRef == code)
.SingleOrDefault();
if(thisSrc == null)
return Enumerable.Empty<MemberObj>();
//Filter Members by sourceId and map the results to a MemberDTO with less fields
var data = (from m in db.Members
where m.sourceId == thisSrc.sourceId
select new MemberDTO
{
MemberId = m.memId,
//map the rest of your DTO fields..
}).ToList();
return data;
}

Remove Item From Object SubList (LINQ)

I have an object that looks like this :
public class Consortium
{
public string Id { get; set; }
[JsonConverter(typeof(EnumDescriptionConverter))]
public SourceType Type { get; set; }
public List<UserLibrary> Branches { get; set; }
}
Each Consortium has a list of UserLibrary's associated with it, and that class looks like this :
public class UserLibrary
{
public string LibraryId { get; set; }
public string RetailerId {get; set;}
public string UserId { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
}
I have a method which will allow the user to remove a library from one of their consortium (note: There may be many branches associated to the consortium).
However, I'm only being supplied a LibraryId, so I'm forced to traverse their list of Consortium, find which one contains the given id, then iterate over the branches and remove the one that matches the id.
Here is how I'm currently accomplishing this :
// Get the current list of consortiums
var user = _mediator.Send(new GetUserProfileCommand { UserProfileId = _principle.UserProfileId });
var userConsortia = user.SavedConsortia;
// the consortium to remove the library from
var branchToRemove = _libraryService.GetLibrary(id);
var consortRemove = new UserConsortium();
foreach (var userConsortium in userConsortia)
{
if (userConsortium.Branches.FirstOrDefault(c => string.Equals(c.LibraryId, id, StringComparison.OrdinalIgnoreCase)) != null)
{
consortRemove = userConsortium;
}
}
// if the consortium id is null, something is f*
if (consortRemove.Id == null)
{
return new JsonDotNetResult(HttpStatusCode.BadRequest);
}
// first remove the consortia
userConsortia.Remove(consortRemove);
// remove the branch from the consortium
consortRemove.Branches.RemoveAll(ul => string.Equals(ul.LibraryId, id, StringComparison.OrdinalIgnoreCase));
// add it back in without the branch
userConsortia.Add(consortRemove);
Question :
Is there a LINQ expression I'm missing here that can help me consolidate this logic, or is there a better way of doing this?
Yes, there are a few approaches you can take depending on taste. The easiest way to simplify what you've got would be this:
var branchToRemove = _libraryService.GetLibrary(id);
// .Single() will throw an exception unless there is one and only one match.
var consortRemove = userConsortia.Single(
c => c.Branches.Any(
b => string.Equals(b.LibraryId, id, StringComparison.OrdinalIgnoreCase));
// remove the consortia
userConsortia.Remove(consortRemove);
Why not something like this? It looks to me from your code that you want to remove the targeted "removal branch" from all consortiums in you collection.
foreach (UserConsortium userConsortium in userConsortia)
{
userConsortium.Branches.RemoveAll(c => string.Equals(c.LibraryId, id, StringComparison.OrdinalIgnoreCase));
}

NHibernate: (Fluent) Mapping / Querying based upon a Getter that accesses an already mapped collection property

I don't know how to phrase this properly. I'm working with a pre-existing domain, where certain entities can contain children that are versioned. The children are responsible for their own version number, but ultimately, this version number only makes sense in context of the attached parent entity.
public class Blog
{
public virtual IList<VersionedItem> VersionedItems { get; set; }
public virtual CurrentVersionedItem {
get {
return VersionedItems.OrderByDescending(x => x.Version).FirstOrDefault();
}
}
}
public class VersionedItem
{
public virtual Blog { get;set; }
public virtual int Version { get; set; }
public virtual string Content { get; set; }
public virtual int SomeNumber { get; set; }
}
And what I'd like to achieve:
var blogs = Session.Query<Blog>(x=> x.CurrentVersionedItem.SomeNumber == 5)
While the IQueryable provider of NHibernate is forgiving, I will not eat everything. Is there a way to define a (fluent) mapping that resolves the "CurrentVersionedItem" property properly?
I'm also aware of the fact CurrentVersionedItem could potentially return null in this scenario (if it worked in the first place).
Why won't you do like this:
var item = session.Query<VersionedItem>().FirstOrDefault(q => q.SomeNumber == 5);
Blog blog;
if (item != null)
blog = item.Blog;

Categories

Resources