I have following object
public class bizObj
{
public string name { get; set; }
public int p_id { get; set; }
public string acc_number { get; set; }
public string a_name { get; set; }
public string a_phone { get; set; }
public virtual product product { get; set; }
public virtual account account { get; set; }
}
Linq statment to get data from db is
public IEnumerable<bizObj> GetbizObj(int id)
{
var acs = (from c in db.p_account
where c.p_id==id
select new bizObj
{
name = c.p_name,
p_id = c.product.id,
acc_number=c.account.acc_number,
a_name = c.a_name,
a_phone = c.a_phone
});
return acs;
}
The above code is working fine but it is returning one collection. What I am trying to
get is that it has a collection of
{
name,
p_id
//than a second collection which has all the records that have same name ane p_id
{
acc_number,
a_name
a_phone
}
}
Please let me know how I can accomplish this using linq/lambda expression. Thanks
Question is unclear, but it looks like you're saying you want to group rows by name and p_id.
var query = acs.GroupBy(x => new { x.name, x.p_id })
.Select(g => new { g.Key.name, g.Key.p_id, Items = g.ToList() });
Related
I have a stored proc returning a datatable using a stored procedure. I am able to convert the it to an object using the following code
outgoingPaymentData.AsEnumerable().Select(x => new OutgoingPaymentApprovalDetails() { });
Here is my OutgoingPaymentApprovalDetails class
public class OutgoingPaymentApprovalDetails
{
public int OriginatorId { get; set; }
public string Name { get; set; }
public string DocumentId { get; set; }
public string DebtorName { get; set; }
public string Currency { get; set; }
public double Amount { get; set; }
public string Description { get; set; }
public string DebitAccountNo { get; set; }
public string CreditAccountNo { get; set; }
}
Now, instead of a flat list, I need to add heirarchy, to select this one object to 3 objects.
Classes as under:
public class OriginatorDetails
{
public int OriginatorId { get; set; }
public string Name { get; set; }
public List<DocumentDetails> DocumentDetails { get; set; }
}
public class DocumentDetails
{
public string DocumentId { get; set; }
public List<TransactionDetails> TransactionDetails { get; set; }
}
public class TransactionDetails
{
public string Amount { get; set; }
public string DebitAccountNo { get; set; }
public string CreditAccountNo { get; set; }
}
Basically, All Documents of a particular Originator have to be in the list of DocumentDetails and all TransactionDetails of a particular document have to be in that list.
One way is to create a dictionary and add stuff in it and finally create an object. I was wondering if there was a more abbreviated and efficient way to do something like this.
TIA
You can do the grouping of retrieved records of OutgoingPaymentApprovalDetails using Linq to create the nested object of OriginatorDetails collection.
see below code
var originalDetails = inputs.GroupBy(g => g.OriginatorId)
.Select(g => new OriginatorDetails()
{
OriginatorId = g.Key,
Name = g.First().Name,
DocumentDetails = g.GroupBy(d => d.DocumentId)
.Select(d => new DocumentDetails()
{
DocumentId = d.Key,
TransactionDetails = d.Select(t => new TransactionDetails()
{
DebitAccountNo = t.DebitAccountNo,
CreditAccountNo = t.CreditAccountNo,
Amount = t.Amount.ToString()
}).ToList()
})
.ToList()
});
Check the created https://dotnetfiddle.net/FCA7Qc to demostrate your scenario.
Try this code:
Basically you need to group 2 times, first time by OriginatorId and Name and then by DocumentId like this:
var result = list.GroupBy(c => new {c.OriginatorId, c.Name})
.Select(g => new OriginatorDetails()
{
Name = g.Key.Name,
OriginatorId = g.Key.OriginatorId,
DocumentDetails = g
.GroupBy(dd => dd.DocumentId)
.Select(dd => new DocumentDetails()
{
DocumentId = dd.Key,
TransactionDetails = dd.ToList()
.Select(td => new TransactionDetails()
{
Amount = td.Amount.ToString(),
CreditAccountNo = td.CreditAccountNo,
DebitAccountNo = td.DebitAccountNo
}).ToList()
}).ToList()
}).ToList();
I have the following entity classes for my database:
[Table("Results")]
public class ResultsEntity
{
[Key]
public Guid Id { get; set; }
public Guid ComponentId { get; set; }
[ForeignKey("ComponentId")]
public ComponentEntity Component { get; set; }
public Status Status { get; set; }
public decimal Value { get; set; }
public string Units { get; set; }
public DateTime CreatedAt { get; set; }
}
[Table("Components")]
public class ComponentEntity
{
[Key]
public Guid Id { get; set; }
public string Title { get; set; }
public string IconCode { get; set; }
}
I want to query my Results table and get the result information plus the ComponentEntity Title (from the Components table). They are connected through the foreign key of the ComponentId Guid. This is my first time querying a SQL database with C# and I am struggling to find the correct syntax. My attempt so far is as follows:
IQueryable<ResultsEntity> resultQuery =
from results in _dbContext.Results
select results;
foreach (ResultsEntity result in resultQuery)
{
var resultData = new ResultData
{
Id = result.Id,
Status = result.Status,
Primary = result.Value,
Units = result.Units,
// How can I get the title of the component here?
};
}
}
Can anyone point me in the right direction please? Thanks
Try
_dbContext.Results.Include(e => e.Component).Select(item =>
new ResultData
{
Id = item.Id,
Status = item.Status,
Primary = item.Value,
Units = item.Units,
Title = item.Component.Title
};);
You include Component here to fill it with your values from DB. After it you can use your Component field in ResultsEntity to get necessary values.
You can join it by using the following linq query
from results in _dbContext.Results
.Include(r => r.ComponentEntity)
select results;
I don't want to use .include to get the entire child tables. I just need select columns.
public class ProjectTypeDTO {
public string Type { get; set; }
}
public class CourseDTO {
public string CourseCode { get; set; }
public string CourseTitle { get; set; }
}
public class ProjectDTO {
public int Id { get; set; }
public ProjectTypeDTO ProjectType { get; set; }
public CourseDTO Course { get; set; }
public string StartTerm { get; set; }
public DateTime SignOff { get; set; }
public DateTime StartDateTime { get; set; }
}
[HttpGet("getallprojects")]
public IActionResult GetAllProjects()
{
var projects = _context.Projects
.Select(p => new ProjectDTO
{
Id = p.Id,
ProjectType = { Type = p.ProjectType.Type },
Course = { CourseCode = p.Course.CourseCode, CourseTitle = p.Course.CourseTitle },
StartTerm = p.StartTerm,
SignOff = p.SignOff,
StartDateTime = p.StartDateTime,
}).ToList();
return Ok(projects);
}
This is throwing a "NotImplementedException: The method or operation is not implemented." error.
I've tested it as an anonymous function and it works.
var projects = _context.Projects
.Select(p => new
{
p.Id,
p.ProjectType.Type,
p.SignOff,
p.StartDateTime,
p.Course.CourseCode,
p.Course.CourseTitle,
p.StartTerm
}).ToList();
An anonymous type won't work for my app, since I need to be able to make changes to this data before it gets returned.
Based on other examples I've seen here and other sites, this looks correct. Could it be a bug?
I haven't seen that syntax for sub-objects before. eg:
ProjectType = { Type = p.ProjectType.Type }
I believe that should be:
ProjectType = new ProjectTypeDTO{ Type = p.ProjectType.Type }
I'm attempting to build an asp.net webforms application to serve as the front end of an sql database.
see database table relations in this image
Simply getting table values is not a problem.
For example displaying values from 'Item' table like this:
var items = from i in db.Items
select new
{
ID = i.Item_ID,
Name = i.Name,
Barcode = i.BarCode,
Description = i.Description,
ItemType = i.ItemType1.ItemTypeName,
LocationCount = i.Location_Item_Juncs.Count
};
GridView1.DataSource = items;
GridView1.DataBind();
looks like this in webforms webpage
Problem is getting something like supplier information for an item.
An item can have multiple 'Supplier', 'Location' and 'ReceivedDate'!
In SQL I can query that information like this:
select Supplier.Name, Supplier.Adress, Supplier.Email, Supplier.Phone, Supplier.Supplier_Zipcode
from item, Supp_Company, Supplier
where Item_ID = 8 and Item_ID = ItemSub_ID and SupplierJunc_ID = Supplier_ID
results look like this in linqpad
These are the suppliers' information for an item with item id of 8.
Notice, there are 3 tables involved in the query (Item, Supp_Company, Supplier) and 2 pairs of values must match to select valid values.
I want to replicate that query in LINQ to use in my web forms app.
I believe the solution to this problem will apply to getting locations and 'received dates' for an item as well.
Is it possible to use a similar 'where' clause in LINQ as I can in SQL? What would the syntax look like?
sure you can, it all depends on the way you build your mappings though.
you've got a many to many scenario in here and you can
map entities relying on link table
map entities relying on link entity
link table approach (notice the modelBuilder HasMany WithMany)
void Main()
{
using (var context = new YourContext())
{
var query = from item in context.Items
from supplier in item.Suppliers
where item.ItemId == 8
select new
{
Name = supplier.Name,
Adress = supplier.Address,
Email = supplier.Email,
Phone = supplier.Phone,
Zip = supplier.Zip,
};
//...
}
}
public class YourContext : DbContext
{
public DbSet<Item> Items { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
public YourContext() : base("MyDb")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>()
.HasMany(item => item.Suppliers)
.WithMany(supplier => supplier.Items)
.Map(m =>
{
m.MapLeftKey("ItemSub_ID");
m.MapRightKey("SupplierJunc_ID");
m.ToTable("Supp_Company");
});
}
}
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public ICollection<Supplier> Suppliers { get; set; }
}
public class Supplier
{
public int SupplierId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Zip { get; set; }
public ICollection<Item> Items { get; set; }
}
link entity approach (notice the modelBuilder maps every table to an entity)
void Main()
{
using (var context = new YourContext())
{
var query = from item in context.Items
join link in context.SupplierItems
on item.ItemId equals link.ItemId
join supplier in context.Suppliers
on link.SupplierId equals supplier.SupplierId
where item.ItemId == 8
select new
{
Name = supplier.Name,
Adress = supplier.Address,
Email = supplier.Email,
Phone = supplier.Phone,
Zip = supplier.Zip,
};
//...
}
}
public class YourContext : DbContext
{
public DbSet<Item> Items { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
public DbSet<SupplierItem> SupplierItems { get; set; }
public YourContext() : base("MyDb")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>()
// ...
;
modelBuilder.Entity<Supplier>()
// ...
;
modelBuilder.Entity<SupplierItem>()
// ...
;
}
}
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
}
public class Supplier
{
public int SupplierId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Zip { get; set; }
}
public class SupplierItem
{
public int ItemId { get; set; }
public int SupplierId { get; set; }
}
Hello I'm using code first approach and I defined the following model:
public partial class tmmodel
{
public tmmodel()
{
this.tmmodel_L10n = new HashSet<tmmodel_L10n>();
}
public int id { get; set; }
public int Order { get; set; }
public bool Active { get; set; }
public virtual ICollection<tmmodel_L10n> tmmodel_L10n { get; set; }
}
public partial class tmmodel_L10n
{
public int modelid { get; set; }
public int CultureId { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public virtual tmmodel tmmodel { get; set; }
}
So I want to get in an anonymous class - the id, Active and order property of my tmodel along with teh title in tmodel_L10:
With Linq i MANAGED TO GET the result - but when I try to use Linq - to - sql - I have some problems :
var items = from i in dc.tmmodel
join l10n in dc.tmmodel_L10n on new { i.id, cid = 1 } equals new { l10n.modelid, cid = l10n.CultureId }
select new
{
id = i.id,
i.Order,
i.Active,
l10n.Title,
};
Here is my - linq to entites query and you can see that I don't have any access to the Title property:
var linqtosqlitems = dc.tmmodel
.Include(x => x.tmmodel_L10n)
.Select(l => new {id = l.id,l.Active,**l.tmmodel_L10n.??**}).ToList();
By using include Linq Creates an Enumarable of your "child" table because it can be one to many relationship. If You are sure there is only one record in "child table" You can go like:
var linqtosqlitems = dc.tmmodel
.Include(x => x.tmmodel_L10n)
.Select(l => new {id = l.id,l.Active,l.tmmodel_L10n.FirstOrDefault().Title}).ToList();