I have this classes in Code First asp.net
public class Account
{
[Key]
public int Id { get; set; }
[Column(TypeName = "nvarchar(100)")]
public string AccountTitle { get; set; }
public Classification Classification { get; set; }
}
public class Classification
{
[Key]
public int Id { get; set; }
[Column(TypeName = "nvarchar(100)")]
public string TitleClassification { get; set; }
public ICollection<Account> Accounts { get; set; }
}
public class ClassificationDto
{
public int Id { get; set; }
public string TitleClassification { get; set; }
}
In my Db Context
public DbSet<Account> Accounts { get; set; }
AccountingManager.FindAll is this
public IQueryable<T> FindAll()
{
return context.Set<T>().AsNoTracking().AsQueryable();
}
I am trying to get just the "Classification" which is just 3 but I am getting the "Account" that is associated with it too with this code:
[HttpGet]
[Route("get-classification")]
[Authorize]
public async Task<IActionResult> GetAccountClassification()
{
List<ClassificationDto> classificationList = new List<ClassificationDto>();
var accountingManager = new AccountingManager(context);
var list = accountingManager.FindAll();
classificationList = await list.Select(s => new ClassificationDto
{
Id = s.Classification.Id,
TitleClassification = s.Classification.TitleClassification,
}).ToListAsync();
return StatusCode(StatusCodes.Status200OK, classificationList);
}
This is how it is in my table
If you want to get all rows from Classification table,
add public DbSet<Classification> Classifications { get; set;} property to your DbContext class. And then implement similar to FindAll() method:
return context.Classifications.AsNoTracking().ToList()
Related
I'm building a feature with a jquery datatable, the idea is to have a list of stores in the parent row, and then when expanding the parent to list all the licensed terminals in child rows that are linked to the store parent row by a StoreLicenseId column. The issue I am having is that I have a ViewModel with two models, one for the list of stores and one for the licensed terminals. I'm busy building the method into my controller, my problem is in the second part of the method where I new up "StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()", all the references to tl.terminalId and tl.Terminalname. I get this error "StoreListViewModel does not contain a definition for TerminalID and no accessible extension method". I can see why this is happening, so my question really is, how do I include this "second" TerminalListViewModel into my method to form part of the query ?
ViewModel
public partial class StoreListViewModel
{
public List<TerminalListViewModel> StoreLicenseDetails { get; set; } = null!;
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
[DisplayName("Store Name")]
public string StoreName { get; set; } = null!;
[DisplayName("App One Licenses")]
public int QtyAppOneLicenses { get; set; }
[DisplayName("App Two Licenses")]
public int QtyAppTwoLicenses { get; set; }
[DisplayName("Date Licensed")]
public DateTime DateLicensed { get; set; }
[DisplayName("Licensed Days")]
public int LicenseDays { get; set; }
[DisplayName("Is License Active")]
public bool LicenseIsActive { get; set; }
}
public partial class TerminalListViewModel
{
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
public Guid TerminalId { get; set; }
public string TerminalName { get; set; } = null!;
public string LicenseType { get; set; } = null!;
public int TerminalLicenseDays { get; set; }
public DateTime DateLicensed { get; set; }
public bool LicenseIsActive { get; set; }
public bool IsDecommissioned { get; set; }
public DateTime LastLicenseCheck { get; set; }
}
Controller Method
//sl = StoreList
//tl = TerminalList
public IEnumerable<StoreListViewModel> GetStoreList()
{
return GetStoreList().GroupBy(sl => new { sl.StoreLicenseId, sl.StoreName, sl.QtyAppOneLicenses,
sl.QtyAppTwoLicenses, sl.DateLicensed, sl.LicenseDays,
sl.LicenseIsActive })
.Select(sl => new StoreListViewModel()
{
StoreName = sl.Key.StoreName,
QtyAppOneLicenses = sl.Key.QtyAppOneLicenses,
QtyAppTwoLicenses = sl.Key.QtyAppTwoLicenses,
DateLicensed = sl.Key.DateLicensed,
LicenseDays = sl.Key.LicenseDays,
LicenseIsActive = sl.Key.LicenseIsActive,
StoreLicenseId = sl.FirstOrDefault().StoreLicenseId,
StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()
{
StoreLicenseId = tl.StoreLicenseId,
TerminalId = tl.TerminalId,
TerminalName = tl.TerminalName,
}).ToList()
}).ToList();
}
Based on the error,I suppose your GetStoreList() method returns List<OrderListViewModel> ,but your OrderListViewModel doesn't contains properties of TerminalListViewModel,So you got the error
GetStoreList() method should return List<SourceModel>( Source is the model which contains all the properties of StoreListViewModel and TerminalListViewModel)
For example,the link your provided:Multiple child rows in datatable, data from sql server in asp.net core
public class OrderList
{
//source of properties of OrderListViewModel(parent rows)
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
//source of properties of OrderListDetailViewModel(child rows)
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
public class OrderListViewModel
{
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
public List<OrderListDetailViewModel> OrderListDetails { get; set; }
}
public class OrderListDetailViewModel
{
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
Orderlist contains all columns OrderListViewModel and OrderListDetailViewModel needs.
When it comes to your case,you should
create 3 models (source,parentrow,childrows)
model for parentrows contains the properties
StoreLicenseId,StoreName, QtyAppOneLicenses,QtyAppTwoLicenses, DateLicensed, LicenseDays,LicenseIsActive
and model for childrows contains the other properties of source model
If you still have questions,please show the data you pulled form db,and I'll write a demo for you
I have Products, Sub products, and more tables. You can see in the code, relationship not working I want it Product Class relationship with SubProduct but always the collection count is 0.
Product Class:
[Key]
public int Id { get; set; }
public bool Status { get; set; } = true;
public string StockCode { get; set; }
public int StockDecrease { get; set; }
public string Name { get; set; }
public int Amount { get; set; }
public int Desi { get; set; }
public string Barcode { get; set; }
public long Gtin { get; set; }
public string InvoiceName { get; set; }
public string EInvoiceName { get; set; }
public string Subtitle { get; set; }
public byte Kdv { get; set; }
public virtual Category Category { get; set; }
public string Description { get; set; }
public virtual ICollection<SubProduct> SubProducts { get; set; }
public virtual ICollection<ProductVariant> ProductVariants { get; set; }
Sub Product Class:
public int Id { get; set; }
public int ProductId { get; set; }
public virtual Product Product { get; set; }
public string StockCode { get; set; }
public virtual ProductBrand Brand { get; set; }
public virtual Company Company { get; set; }
public Abstract.Marketplace Marketplace { get; set; }
public string Barcode { get; set; }
public string Title { get; set; }
public string SubTitle { get; set; }
public bool IsConnected { get; set; }
public decimal Price { get; set; }
public decimal PriceDiscount { get; set; }
public string Description { get; set; }
public virtual ICollection<SubProductVariant> SubProductVariants { get; set; }
Repository Base:
public async System.Threading.Tasks.Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> filter)
{
await using var context = new TContext();
return await context.Set<TEntity>().Where(filter).SingleOrDefaultAsync();
}
Make sure to add using System.Data.Entity; to get the version of Include that takes in a lambda.
using System.Data.Entity;
query.Include(x => x.SubProducts)
and for more use ThenInclude or Include extention methods.
To define a method on the repository for this, you can use this example:
public static IQueryable<TSource> GetIQueryableWithIncludes<TSource>(Expression<Func<TSource, object>>[] includeProperties, IQueryable<TSource> result)
{
var newResult = result;
if (includeProperties.Any())
{
foreach (var includeProperty in includeProperties)
{
newResult = newResult.Include(includeProperty);
}
}
return newResult;
}
You can now pass a list of lamba expression like p => p.SubProjects to specify what you want to include.
You can further hide this by making an GetAll method that hides these includes from the outside user of your Domain
I would suggest to first study more about how to handle related entities.
You basically need to tell EF to load them in.
See documentation
Simplest example would something like this:
// Load all products.
var products= context.Products
.Include(b => b.SubProducts)
.ToList();
I solved with .Include() thanks for helping.
public async System.Threading.Tasks.Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> filter, Expression<Func<TEntity,object>> include=null)
{
await using var context = new TContext();
return await context.Set<TEntity>().Where(filter).Include(include).SingleOrDefaultAsync(filter);
}
I have the following POCO classes:
public class Employees
{
public int EmployeeId
{
get;
set;
}
public int EmpImageId
{
get;
set;
}
public string EmployeePhotoUrl
{
get;
set;
}
public string EmpAddress
{
get;
set;
}
}
public class Images
{
public int ImageId
{
get;
set;
}
public string ImageUrl
{
get;
set;
}
public string ImgCode
{
get;
set;
}
}
public class EmployeeDTO
{
public int EmployeeId
{
get;
set;
}
public int EmpImageId
{
get;
set;
}
public string EmployeePhotoUrl
{
get;
set;
}
public string EmpAddress
{
get;
set;
}
}
While getting the list of Employees present in the system, for each Employee, the photourl (EmployeePhotoUrl) is fetched from the Images table using the EmpImageId property.
// Get the list of Employees
var employees = await _dbContext.Employees
.Select(ef => new EmployeeDTO
{
EmployeeId= ef.EmployeeId,
EmployeePhotoUrl = images.FirstOrDefault(im => im.ImageId.Equals(ef.EmpImageId)).EmployeePhotoUrl,
EmpAddress = ef.EmpAddress
}).Skip((pageNo - 1) * 100).Take(pageSize).ToListAsync();
I want to leverage Automapper in this case. The issue I see here is the assignment of EmployeePhotoUrl, since this property is fetched from another entity: Images
Can anyone help me to know how to leverage Automapper in this case.
I need to show nested table and i'm getting data using Ajax.
I tried to return directly from database as JSON but that gave me Circular Exception Reference.
So i created a View Model similar to my model but i can't to figure out how to pass data from it without having to write a lot of code with loops and pass by property
here are the models
public class Inventory
{
public int Id { get; set; }
public decimal Name{ get; set; }
public ICollection<StorageUnit> StorageUnits { get; set; }
}
public class StorageUnits
{
public int Id { get; set; }
public string Name{ get; set; }
public virtual Inventory Inventory { get; set; }
}
public class InventoryViewModel
{
public int Id { get; set; }
public string Name{ get; set; }
public ICollection<StorageUnit> StorageUnits { get; set; }
}
public class StorageUnitsViewModel
{
public int Id { get; set; }
public string Name{ get; set; }
public virtual Inventory Inventory { get; set; }
}
and the controller
public async Task<ActionResult> GetInventories()
{
var inventories = await db.Inventory
.Include(i => i.StorageUnits)
.ToListAsync();
var inventoryViewList = new List<InventoryViewModel>();
foreach (var item in inventories)
{
inventoryViewList.Add(new InventoryViewModel
{
Id = item.Id,
Name = item.Name,
StorageUnit = item.StorageUnit // Gives error missing cast
});
}
return Json(inventoryViewList, JsonRequestBehavior.AllowGet);
}
Inventory model that Name property is decimal and in InventoryViewModel property Name is string, is it right?
you can use this code instead of loops:
var inventoryViewList = inventories.Select(x => new InventoryViewModel()
{
Id = x.Id,
Name = x.Name.ToString(),
StorageUnits = x.StorageUnits
}).ToList();
you have a error because your object is null and should change your InventoryViewModel to:
public class InventoryViewModel
{
public InventoryViewModel()
{
this.StorageUnits = new List<StorageUnit>();
}
public int Id { get; set; }
public string Name { get; set; }
public ICollection<StorageUnit> StorageUnits { get; set; }
}
You can use a library - AutoMapper
Like this
Mapper.Initialize(cfg=>cfg.CreateMap<Inventory, InventoryViewModel>());
var inventories =
Mapper.Map<IEnumerable<Inventory>, List<InventoryViewModel>>(repo.GetAll());
Sql Tables Here
public partial class Users
{
public Users()
{
UsersRelationFollower = new HashSet<UsersRelation>();
UsersRelationFollowing = new HashSet<UsersRelation>();
Vote = new HashSet<Vote>();
VoteRating = new HashSet<VoteRating>();
}
public string Id { get; set; }
public string UserType { get; set; }
public string UserName { get; set; }
public string Mail { get; set; }
public string ImageUrl { get; set; }
public DateTime CreationDate { get; set; }
public DateTime? ModifyDate { get; set; }
public bool State { get; set; }
public virtual UserPasswords UserPasswords { get; set; }
public virtual CorporateProperty CorporateProperty { get; set; }
public virtual UserProperty UserProperty { get; set; }
public virtual ICollection<UsersRelation> UsersRelationFollower { get; set; }
public virtual ICollection<UsersRelation> UsersRelationFollowing { get; set; }
public virtual ICollection<Vote> Vote { get; set; }
public virtual ICollection<VoteRating> VoteRating { get; set; }
}
public partial class UserProperty
{
public string Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public DateTime BirthDay { get; set; }
public string Gender { get; set; }
public string Locale { get; set; }
public string PhoneNumber { get; set; }
public bool State { get; set; }
public virtual Users IdNavigation { get; set; }
}
public partial class CorporateProperty
{
public string Id { get; set; }
public string OrganisationName { get; set; }
public string Website { get; set; }
public bool State { get; set; }
public virtual Users IdNavigation { get; set; }
}
UserControllerClass
// GET: api/Users/5
[HttpGet("{id}")]
public async Task<IActionResult> GetUsers([FromRoute] string id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var users = await _context.Users.SingleOrDefaultAsync(m => m.Id == id);
if (users == null)
{
return NotFound();
}
return Ok(users);
}
My problem is exactly this; User information is coming but the password and property table information is not coming.
How to modify the following line solves my problem?
var users = await _context.Users.SingleOrDefaultAsync(m => m.Id == id);
based on your code this would also hydrate your CorporateProperty & UseProperty objects, etc.
var user = await _context.Users.Include(user => user.UserProperty).Include
(user => user.CorporateProperty).SingleOrDefaultAsync(user => user.Id == id);
lazy loading doesn't exist yet so you have Eager Loading to play with for now.
Surprised you didn't roll with Identity since this all of this would have been taken care for you especially Passwords... Hope you aren't rolling your own hash for that..
Just add in the custom class / collection objects you need.
you can also check out this link
https://learn.microsoft.com/en-us/ef/core/querying/related-data