I have a problem with sum of navigation properties using entity framework
Here is my example classes
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ObservableCollection<Call> Calls { get; set; }
[NotMapped]
public decimal TotalCallDuration { get { return Calls.Sum(c => c.Value); } }
}
public class Call
{
public int Id { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
public decimal Value { get; set; }
public DateTime Date { get; set; }
}
This works well but when i have hundreds of records it is very slow
How can i make this faster but without losing functionality?
Thanks
what you want to do is:
customer.TotalCallDuration = context.Call.Sum(x => x.Value).Where(x => x.CustomerID == customer.Id);
Related
Is there a better way to load all the related entities?
Below is the ScholarshipRequest class which also has Scholarship, Status, Student, Program and User.
public class ScholarshipRequest
{
public int Id { get; set; }
public int Year { get; set; }
public Status Status { get; set; }
public DateTime ApplicationDate { get; set; }
public DateTime ActionDate { get; set; }
public Scholarship Scholarship { get; set; }
public Program Program { get; set; }
public Student Student { get; set; }
public User User { get; set; }
}
I am just posting Scholarship class here, rest are similar.
public class Scholarship
{
public int Id { get; set; }
public string Name { get; set; }
}
The below code works fine but is there a better way where i can use a single .Include() to load them all or may be some other way?
ScholarshipRequestRepository repo = new ScholarshipRequestRepository(dBContext);
List<ScholarshipRequest> stdList = repo.Collection()
.Include("Status").Include("Student").Include("User").Include("Scholarship")
.Where(x => x.User.Id == userId).ToList();
I need to store type safe entity key/value pairs in EF Core.
Key Value Types
// KeyValuePair<string,bool>
// KeyValuePair<string,int>
// KeyValuePair<string,string>
// KeyValuePair<string,float>
// KeyValuePair<string,DateTime>
Entity
public class MyEntity
{
public int Id { get; set; }
public List<KeyValuePair<string,T>> Attributes { get; set; }
}
Elsewhere
{
…
dbContext.MyEntity.Add(new KeyValuePair<string,bool>("Active", true);
dbContext.MyEntity.Add(new KeyValuePair<string,string>("Customer", "Microsoft");
dbContext.MyEntity.Add(new KeyValuePair<string,string>("Street", "1 Microsoft Way");
dbContext.MyEntity.Add(new KeyValuePair<string,float>("Rating",5.0);
}
How can this be accomplished in EF Core?
I know it's a bit late for an answer, but I had the same problem trying to persist keyvalue pairs.
The only way I found was to strong type them, since EF has no clue on how to persist the KeyValue entity.
Here's my model:
public class Payment
{
//-- Properties
public int PaymentId { get; set; }
public decimal Amount { get; set; }
public string Currency { get; set; }
public virtual List<PaymentField> PaymentFields { get; set; } = new List<PaymentField>();
}
public class PaymentField
{
//-- Properties
[Key]
public int PaymentFieldId { get; set; }
// References master table
public int PaymentId { get; set; }
public virtual Payment Payment { get; set; }
public virtual List<PaymentFieldItem> PaymentFieldItems { get; set; } = new List<PaymentFieldItem>();
}
public class PaymentFieldItem
{
public int PaymentFieldItemId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public int PaymentFieldId { get; set; }
public virtual PaymentField PaymentField { get; set; }
}
Hope you can adjust to your own needs.
I'm using Entity Framework 6.0 and have defined 2 POCO's to map to my database:
[Table("PortfolioGroups")]
public class PortfolioGroup : AuditableEntity<int>
{
[Column("Company_Id")]
public int CompanyId { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<PortfolioGroupItem> PortfolioGroupItems { get; set; }
public PortfolioGroup()
{
PortfolioGroupItems = new Collection<PortfolioGroupItem>();
}
}
And the PortfolioGroupItem:
[Table("PortfolioGroupItems")]
public class PortfolioGroupItem : AuditableEntity<int>
{
[Column("PortfolioGroup_Id")]
public int PortfolioGroupId { get; set; }
[ForeignKey("PortfolioGroupId")]
public PortfolioGroup PortfolioGroup { get; set; }
[Column("Trademark_Id")]
public int? TrademarkId { get; set; }
[ForeignKey("TrademarkId")]
public Trademark.Trademark Trademark { get; set; }
[Column("TrademarkRegistration_Id")]
public int? TrademarkRegistrationId { get; set; }
[ForeignKey("TrademarkRegistrationId")]
public TrademarkRegistration TrademarkRegistration { get; set; }
[Column("Domain_Id")]
public int? DomainId { get; set; }
[ForeignKey("DomainId")]
public Domains.Domain Domain { get; set; }
}
However - when I attempt to query the PortfolioGroups, Entity Framework for some reason attempts to query a field named "Trademark_Id" - which doesn't exist on the PortfolioGroup entity:
Context.PortfolioGroups.SingleOrDefault(i => i.Id == id && i.CompanyId == companyId);
Throws:
Invalid column name 'Trademark_Id'.
I've used this kind of setup other places in my application without any problems. I simply cannot find out why EF is trying to query a column that's not in my entity!
Any suggestions would be greatly appreciated. I'm at the end of my rope here.
Thanks guys! :)
The problem is that you've added a Navigation Property on Trademark that requires a Foreign Key on Portfolio Group:
public class Trademark
{
[Key]
public int Id { get; set; }
[MaxLength(250)]
[Required]
public string Name { get; set; }
[MaxLength(150)]
public string Filename { get; set; }
public ICollection<PortfolioGroup> PortfolioGroups { get; set; }
public Trademark()
{
PortfolioGroups = new Collection<PortfolioGroup>();
}
}
EF expects PortfolioGorup to have a Trademark_ID column to store which PortfolioGroups are associated with a Trademark.
Hi I am trying to return all vehicles with their recorded mileage through an api using ASP.Net Core with the following code:
// GET: api/values
[HttpGet]
public IEnumerable<Vehicle> Get()
{
return _context.Vehicles.Include(m=>m.Mileages).ToList();
}
However this only returns the first vehicle with its mileages and not the others (there are five dummy vehicles in the db all with an initial mileage).
If I change the code to:
// GET: api/values
[HttpGet]
public IEnumerable<Vehicle> Get()
{
return _context.Vehicles.ToList();
}
it returns the full list of vehicles but no mileage.
My class files are:
public class Vehicle
{
public Vehicle()
{
Mileages = new List<Mileage>();
}
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public ICollection<Mileage> Mileages { get; set; }
}
and
public class Mileage
{
public int Id { get; set; }
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
//Navigation Properties
public int VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
}
thanks for looking!
Tuppers
you can have them auto-load (lazy loading) using proxies... but for that, your foreign entities and collections must be marked virtual in your POCOs:
public class Mileage
{
public int Id { get; set; }
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
//Navigation Properties
public int VehicleId { get; set; }
public virtual Vehicle Vehicle { get; set; }
}
public class Vehicle
{
public Vehicle()
{
Mileages = new List<Mileage>();
}
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public virtual ICollection<Mileage> Mileages { get; set; }
}
The proxy creation and lazy loading turned on, but that's the default in EF6.
https://msdn.microsoft.com/en-us/data/jj574232.aspx
Let me know if this works.
Well after a lot of searching I managed to find a solution. I used the following:
[HttpGet]
public IEnumerable<VehicleDto> Get()
{
var query = _context.Vehicles.Select(v => new VehicleDto
{
Registration = v.Registration,
Make = v.Make,
Model = v.Model,
Marked = v.Marked,
Mileages = v.Mileages.Select(m => new MileageDto
{
MileageDate = m.MileageDate,
RecordedMileage = m.RecordedMileage
})
.ToList(),
})
.ToList();
return (IEnumerable<VehicleDto>) query.AsEnumerable();
this doesn't seem to be the most elegant way of doing this, if anyone could offer any advice but it does return what is required.
The DTO's look like:
public class VehicleDto
{
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public ICollection<MileageDto> Mileages { get; set; }
}
and
public class MileageDto
{
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
}
Thanks for taking the time to look at this
Tuppers
I am working on Web-API project and using Entity Framework with Generic Repository and Unit Of work. Basically i follow a tutorial for this.
Here is my table architecture.
Entity
public class ProductEntity
{
public int ProductId { get; set; }
public string ProductCode { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
public string ProductImgName { get; set; }
public bool IsActive { get; set; }
public int PrimaryCatId { get; set; }
public int SecondaryCatId { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public System.DateTime CreateDate { get; set; }
public List<PrimaryProductEntity> objPrimaryProduct { get; set; }
public List<SecondaryProductEntity> objSecondaryProduct { get; set; }
}
public class PrimaryProductEntity
{
public int PrimaryCatId { get; set; }
public string PrimaryCatName { get; set; }
}
public class SecondaryProductEntity
{
public int SecondaryCatId { get; set; }
public string SecondaryCatName { get; set; }
public int PrimaryCatId { get; set; }
}
Services Code
public IEnumerable<BusinessEntities.ProductEntity> GetAllProducts()
{
var products = _unitOfWork.ProductRepository.GetAll().ToList();
var primaryProducts = _unitOfWork.PrimaryProductRepository.GetAll().ToList();
var secondaryProducts = _unitOfWork.SecondaryProductRepository.GetAll().ToList();
if (products.Any())
{
Mapper.CreateMap<tblProduct, ProductEntity>();
var proInfo = from P in products
join PP in primaryProducts on P.PrimaryCatId equals PP.PrimaryCatId
join SP in primaryProducts on P.SecondaryCatId equals SP.SecondaryCatId
select P;
var productsModel = Mapper.Map<List<tblProduct>, List<ProductEntity>>(proInfo);//getting error
return productsModel;
}
return null;
}
i know my implementation is wrong, i don't know what to write in code for fetch data from multiple tables. Please help me.
Required Data
ProductID,ProductName, PrimaryCatName, SecondaryCatName,Price, Quantity
Your Product Entity class Doesn't require a List<PrimaryProductEntity> and List<SecondaryProductEntity>. I suppose according to your class diagram Each Product is associated with one PrimaryProductEntity and one SecondaryProductEntity.
Once your model class is corrected, you would be able to access the properties of the navigation. I am not so good with writing a Query the way you want. But i hope you could get an idea of what you should be doing