public class Parent {
public int Id { get; set; }
public string Name { get; set; }
public Child ChildField { get; set; }
}
public class Child {
public int Id { get; set; }
public int Age { get; set; }
public int ParentId { get; set; }
}
public class MyDbContext : DbContext {
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Childs { get; set; }
}
DB Rows:
parent_id | name
1 "Parent 1"
2 "Parent 2"
Child Rows
child_id | age | parent_id
3 15 1
4 21 2
I have a method that looks like this:
public Parent Get(int parentId) {
var result = this.dbContext.Parents
.Join(
this.dbContext.Childs,
p => p.Id,
c => c.ParentId,
(p, c) => new { Parent = p, Child = c })
.AsNoTracking().Where(m => m.Parent.Id == parentId)
.FirstOrDefault()
result.Parent.Child = result.Child;
return result.Parent;
}
This is currently working for me, but I'd like to not have to manually assign the child to the parent after this join.
Is there a better way to do this? I would like to use this same style of syntax.
How can I accomplish this without having to manually assign the Child to the Parent?
Thanks!
The including...
FatherRepository.All().Including(x => x.Childs, x => x.Childs.Select(y => y.ChildChild));
Father class...
public class Father
{
public int Id { get; set; }
#region Navigations Properties
public virtual List<Child> Childs { get; set; }
#endregion
}
Child class...
public class Child
{
public int Id { get; set; }
public int ChildChildId { get; set; }
public int FatherId { get; set; }
#region Navigations Properties
public virtual Father Father { get; set; }
public virtual ChildChild ChildChild { get; set; }
#endregion
}
ChildChild class...
public class ChildChild
{
public int Id { get; set; }
}
Just write :
var result = this.dbContext.Parents.Where(m => m.Parent.Id == parentId)
.Include(p=>p.Child).FirstOrDefault()
result will contains corresponding childs
Related
i have problem
i have A CategoryEntity Class :
public class Category : IId
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
and SubCategory Entity Class :
public class SubCategory : IId
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
and its my SubToCat entity class :
public class SubToCat
{
public int SubCategoryId { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public SubCategory SubCategory { get; set; }
}
now in Get method for all SubCategory i want to join the all of categories where its CategoryId is same as CategoryId
but i dont know how, Can you plz Help me
I'm assuming you are using some Entity Framework :
_dbContext.SubCategories.Where(s => s.SubToCat.Category == CategoryId)
You do not need join. Just use SelectMany as code below :
class Program
{
static void Main(string[] args)
{
DataContext db = new DataContext();
var results = db.Category.SelectMany(x => x.SubToCat.SelectMany(y => y.SubCategory.SubToCat.Select(z => new {
catId = x.Id,
catName = x.Name,
subToSubCatId = y.SubCategoryId,
subToCatId = y.CategoryId,
subToCategory = y.Category,
subToCatSubCatId = z.SubCategory.Id,
subToCatSubCatName = z.SubCategory.Name
}).ToList():
}
}
public class DataContext
{
public List<Category> Category { get; set; }
}
public class IId
{
}
public class Category : IId
{
public int Id { get; set; }
public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
public class SubCategory : IId
{
public int Id { get; set; }
public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
public class SubToCat
{
public int SubCategoryId { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public SubCategory SubCategory { get; set; }
}
Try
_dbContext.SubCategories
.Include(x => x.SubToCat)
.Include(x => x.Category)
This will bring in all Sub Categories as well the joining table and relevant Categories in a single SQL Query using 2 joins.
I am trying to populate the AllTerms object that will contain LegalFundClassCommercialViewModel and LegalFundClassSideLetterViewModel objects.
Basically the LEGAL_FUND_CLASS table has parent and child records and are related by column LegalParentClassId. One parent has one child. So I need to loop through legalfundClasses object and populate
IEnumerable<LegalFundClassWrapper> AllTerms . The LegalFundClassDetailsViewModel represents the records in the LEGAL_FUND_CLASS table. So legalfundClasses variable contains records from this legal_fund_class table. There are several records. Some records wont have child record. I need to populate in a way where the parent record gets added to LegalFundClassCommercialViewModel and its child record gets added to
LegalFundClassSideLetterViewModel. The wrapper would contain a collection of Parent and child records where some child records wont exist and hence the LegalFundClassSideLetterViewModel property would be null.
Can somebody give me an idea on how to go about it ?
C#
public class LegalFundClassViewModel
{
public IEnumerable<LegalFundClassWrapper> AllTerms;
public class LegalFundClassWrapper
{
public LegalFundClassDetailsViewModel LegalFundClassCommercialViewModel { get; set; }
public LegalFundClassDetailsViewModel LegalFundClassSideLetterViewModel { get; set; }
}
}
public class LegalFundClassDetailsViewModel
{
public string Description { get; set; }
public string AuditSummary { get; set; }
public string FeesReviewSummary { get; set; }
public string TermsReviewSummary { get; set; }
public int Id { get; set; }
public int FundId { get; set; }
public int FundClassType { get; set; }
public int? CurrencyId { get; set; }
public string PrimaryCurrencyName { get; set; }
public string OtherCurrencyName { get; set; }
public int? ManagerStrategyId { get; set; }
public string ManagerStrategyName { get; set; }
public int? SubVotingId { get; set; }
public string SubVotingName { get; set; }
public int? SubHotIssueId { get; set; }
public string SubHotIssueName { get; set; }
public int? RedsFrqncyId { get; set; }
public string RedsFrqncyName { get; set; }
public int? RedsNoticeDays { get; set; }
public int? NoticeTypeOfDaysId { get; set; }
public string NoticeTypeOfDaysName { get; set; }
public int? LegalParentClassId { get; set; }
}
var managerStrategyFundIds = GetService<MANAGERSTRATEGY>().WhereWithIncludes<MANAGERSTRATEGY>(x => x.ID == managerStratedyId, x => x.FUNDs).SelectMany(x => x.FUNDs).Select(x => x.ID).ToList();
var legalfundClasses = GetService<LEGAL_FUND_CLASS>().Where(x => managerStrategyFundIds.Contains(x.FUND_ID));
What I was trying creates a list of all the records in one. How do I loop through and populate the AllTerms
var allFunds = legalfundClasses.Select(fc => new LegalFundClassDetailsViewModel
{
Description = fc.DESCRIPTION,
Id = fc.ID,
FundId = fc.FUND_ID,
FundClassType = fc.CLASS_TYPE,
AuditSummary = getAuditSummary(managerStratedyId, fc.ID),
FeesReviewSummary = getFeesReviewSummary(fc),
TermsReviewSummary = getTermsReviewSummary(fc),
CurrencyId = fc.CURRENCY_ID,
});
public class LegalFundClassViewModel
{
public IEnumerable<LegalFundClassWrapper> AllTerms;
public class LegalFundClassWrapper
{
public LegalFundClassDetailsViewModel
LegalFundClassCommercialViewModel { get; set; }
public LegalFundClassDetailsViewModel
LegalFundClassSideLetterViewModel { get; set; }
}
As you can see in the image below, there are two records. The record that has value in legal_parent_class id field is the child to the record on top of it. If you notice the id of the top record matches the bottom record's legal_parent_class_id.
What is the best way to identify the child and store records in respective properties accordingly
You need left outer join. In your case
var allFunds = new[]
{
new LegalFundClassDetailsViewModel
{
Id = 101,
Description = "Parent with child"
},
new LegalFundClassDetailsViewModel
{
Id = 102,
Description = "Parent without child"
},
new LegalFundClassDetailsViewModel
{
Id = 103,
Description = "I'm child",
LegalParentClassId = 101
}
};
var allTerms = (from fund in allFunds
where fund.LegalParentClassId == null //only parents
join child in allFunds on fund.Id equals child.LegalParentClassId into gj
from child2 in gj.DefaultIfEmpty()
select new LegalFundClassViewModel.LegalFundClassWrapper { LegalFundClassCommercialViewModel = fund, LegalFundClassSideLetterViewModel = child2 })
.ToArray();
I need the id to fetch data collections from my parent.
The plan is to fetch all friends from the repository by using the ParentId.
To illustrate I have a Parent and Child class and also one Mapper each.
I suppose I must define the key in the ParentMapper.
See comment in my code
{
public class Child {
public int IdChild { get; set; }
public string ChildName {get;set;}
// here is the problem
//I need to define ParentID as ForeignKey in some way but how??
//I belive its done in the ParentMapper
public virtual int ParentId { get; set; } //ForeignKey
public virtual ICollection<Friend> Friends { get; set; }
//The plan is to fetch all friends from the repository by using the ParentId and
//keep the entity as clean as possible.
public virtual ICollection<Friend> FamilyFriends { get; set; }
}
public class Parent {
public int IdParent { get; set; }
public string ParentName {get;set;}
public virtual ICollection<Friend> Friends { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
}
{
class ParentMapper : EntityTypeConfiguration<Parent>
{
public ParentMapper()
{
HasKey(one => one.IdParent);
//I started out like this but its not possible....
//But this will give an error obviusly
HasMany(c => c.Children).WithRequired(d => d.ParentId).HasForeignKey(one => one.ParentId);
}
}
}
{
class ChildMapper : EntityTypeConfiguration<Child>
{
public ChildMapper()
{
HasKey(one => one.IdChild);
}
}
}
public class Child {
public int ChildId { get; set; }
public string ChildName {get;set;}
[ForeignKey("Parent")]
public int ParentId { get; set; } //ForeignKey
public Parent Parent{get; set;}
public List<Friend> Friends { get; set; }
public List<Friend> FamilyFriends { get; set; }
}
public class Parent {
public int ParentId { get; set; }
public string ParentName {get;set;}
public List<Friend> Friends { get; set; }
public List<Child> Children { get; set; }
}
public class Friend
{
public int FriendId { get; set; }
public string FriendName {get;set;}
[ForeignKey("Parent")]
public int ParentId{get;set;}
public Friend Parent {get;set;}
[ForeignKey("Child")]
public int ChildId{get;set;}
[InverseProperty("Friends")]
public Child Child {get;set;}
[ForeignKey("ChildFam")]
public int ChildFamId{get;set;}
[InverseProperty("FamilyFriends")]
public Child ChildFam {get;set;}
}
I have my 2 models like below
public class FItem
{
public FItem() { }
public int RecordId { get; set; }
public int MarketId { get; set; }
public string ItemName { get; set; }
public string ItemFamily { get; set; }
public string HoverFamily { get; set; }
public string ItemDesc { get; set; }
public IEnumerable<FSubsystem> FSubsystems { get; set; }
}
public class FSubsystem
{
public FSubsystem() { }
public int FSubsystemId { get; set; }
public int RecordId { get; set; } //Foreign key
public int supplierId { get; set; }
public int SubSystemTypeId { get; set; }
public double Percentage { get; set; }
public double? Value { get; set; }
}
public class FReferences
{
public FReferences() { }
public int RecordID { get; set; } //Foreign key
public int SourceID { get; set; }
public DateTime SourceDate { get; set; }
public string Reference { get; set; }
public int? ReferenceID { get; set; }
}
and I use dapper to fetch the data and put into objects . code is as belolw
using (var multi = mapperConnection.QueryMultiple("USP_FetchMarketRecords", parameters, (SqlTransaction)null, 1000000, CommandType.StoredProcedure))
{
IEnumerable<MarketRecord.FItem> FItem = multi.Read<MarketRecord.FItem>().ToList();
IEnumerable<MarketRecord.FSubsystem> FSubsystem = multi.Read<MarketRecord.FSubsystem>().ToList();
}
Now I want to get the subsystems for each record id and put them in FSubsystems property of Fitem . How can I do this ?
Here I am showing only one one to many relationship to FItem thats Fsubsystem . But I have many one to many tables to Fitem like FReferenc ,FUnit etc . For all foreign key is RecordId itelf.
Can this be done through linq query ? or should I use some diff technique ?
Dapper doesn't include anything built in to reconstruct parent/child relationships from different sets.
You can probably generalize the scenario something like:
static void ApplyParentChild<TParent, TChild, TId>(
this IEnumerable<TParent> parents, IEnumerable<TChild> children,
Func<TParent, TId> id, Func<TChild, TId> parentId,
Action<TParent, TChild> action)
{
var lookup = parents.ToDictionary(id);
foreach (var child in children)
{
TParent parent;
if (lookup.TryGetValue(parentId(child), out parent))
action(parent, child);
}
}
so if we had:
List<Parent> parents = new List<Parent> {
new Parent { Id = 1 },
new Parent { Id = 2 }
};
List<Child> children = new List<Child> {
new Child { Id = 3, ParentId = 1},
new Child { Id = 4, ParentId = 2},
new Child { Id = 5, ParentId = 1}
};
You could use:
parents.ApplyParentChild(children, p => p.Id, c => c.ParentId,
(p,c) => p.Children.Add(c));
For example, with the following classes
public class Child
{
public Guid Id { get; set; }
public String Description { get; set; }
public double Value { get; set; }
public Child()
{
Id = Guid.NewGuid();
}
}
public class Parent
{
public Guid Id { get; set; }
public String Name { get; set; }
public virtual IList<Child> Children { get; set; }
public Parent()
{
Id = Guid.NewGuid();
Children = new List<Child>();
}
}
And context
public class TempContext : DbContext
{
public DbSet<Child> Children { get; set; }
public DbSet<Parent> Parents { get; set; }
}
How could I ensure that the objects in Parent.Children are ordered by Value
TempContext tc = new TempContext();
var parents = tc.Parents.ToList();
foreach (var p in parents)
{
Debug.WriteLine("Parent : {0}", (object) p.Name);
foreach (var c in p.Children)
{
Debug.WriteLine("Child : {0} - {1}", c.Value, c.Description);
}
Debug.WriteLine("");
}
Obviously, I can sort p.Children above before iterating the collection but I'd like the collection to already be ordered.
You must write a query for that. Ordering is not managed by mapping.