I m using Automapper in my project (.net 6). both Table have foreign key relationship. By using automapper mapping insert data, update data and get data from one entities is really flexible. but whenever I do join with query syntax I have to map data manually. I would like to know if there is any way to do this with AutoMapper, and how? so I can skip naming all fields or manual mapping. I used several technique with projecto Function can't find desire result.
My code.
Company Entities
public class Country
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[StringLength(256)]
public string CountryName { get; set; }
[StringLength(6)]
public string CountryAlias { get; set; }
[StringLength(10)]
public string TelephoneCode { get; set; }
}
City Entities
public class City
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[StringLength(256)]
public string CityName { get; set; }
[ForeignKey("CountryId")]
public Country Country { get; set; }
public int CountryId { get; set; }
}
CityDto
public class CityDto
{
public int CountryId { get; set; }
public int Id { get; set; }
public string CityName { get; set; }
public string CountryName { get; set; }
public int CreatedBy { get; set; }
}
API
public async Task<IEnumerable<CityDto>> GetAllCity()
{
return await (from country in _context.Countries
join city in _context.Cities on country.Id equals city.CountryId
orderby country.CountryName, city.CityName
select new CityDto
{
CountryId = city.CountryId,
CountryName = country.CountryName,
Id = city.Id,
CityName = city.CityName,
CreatedBy = city.CreatedBy,
})
.ToListAsync();
}
Related
I want to write a query for the API to get all desired data as JSON while keeping all related tables in the final result. I studied this thread but I could not implement it in my case. I have the following model:
Equipment.cs
public class Equipment
{
[Key]
public long EquipmentId { get; set; }
[Required]
public string EquipmentCode { get; set; }
[Required]
public string EquipmentTitle { get; set; }
[Required]
public bool IsActive { get; set; }
//Navigation properties
[Required]
public int CostCenterId { get; set; }
public CostCenter CostCenter { get; set; }
public int? EquipmentCategoryId { get; set; }
public EquipmentCategory? EquipmentCategory { get; set; }
public int EquipmentTypeId { get; set; }
public EquipmentType equipmentType { get; set; }
}
CostCenter.cs
public class CostCenter
{
[Key]
public int CostCenterId { get; set; }
[Required]
[MaxLength(100)]
public string Title { get; set; }
[Required]
public bool IsActive { get; set; } = true;
//Navigation properties
[JsonIgnore]
public virtual List<Equipment>? Equipments { get; set; }
}
EquipmentCategory.cs
public class EquipmentCategory
{
[Key]
public int EquipmentCategoryId { get; set; }
[Required]
[MaxLength(100)]
public string CategoryCode { get; set; }
[Required]
[MaxLength(100)]
public string CategoryName { get; set; }
//Navigation property
[JsonIgnore]
public virtual List<Equipment>? Equipments { get; set; }
}
EquipmentType.cs
public class EquipmentType
{
[Key]
public int EquipmentTypeId { get; set; }
[Required]
[MaxLength(100)]
public string EquipmentTypeTitle { get; set; }
//Navigation property
[JsonIgnore]
public virtual List<Equipment>? Equipments { get; set; }
}
I use the following codes in the controller:
var query = "SELECT * FROM Equipments INNER JOIN CostCenters ON CostCenters.CostCenterId = Equipments.CostCenterId WHERE EquipmentCode LIKE '1101%'"
var result = connection.Query<Equipment>(query).ToList();
return Ok(result);
First you need to join all tables and then map the relations to Equipment object like this:
var query = #"
SELECT * FROM Equipments INNER JOIN CostCenters ON CostCenters.CostCenterId = Equipments.CostCenterId
INNER JOIN EquipmentCategories ec ON Equipments.EquipmentCategoryId = ec.EquipmentCategoryId
INNER JOIN EquipmentTypes t ON Equipments.EquipmentTypeId = t.EquipmentTypeId
WHERE EquipmentCode LIKE '1101%'";
var result = connection.Query<Equipment,CostCenter,EquipmentCategory,EquipmentType, Equipment>
(query,(equipment, center, category, type)=>{
equipment.CostCenter=center;
equipment.EquipmentCategory=category;
equipment.EquipmentType=type;
return equipment;
}).ToList();
return Ok(result);
We have Customer transactional table with multiple lookup tables with foreign keys. We want to see the 3 table joined together. Should a Repository ever join tables together, or is it only used for reading single tables?
Also if so, what does the example repository place data into? I heard it cannot know about Viewmodels etc, so what object data type would the results go into?
Repository:
void GetByCustomerTransactionId()
{
var result = from ct in CustomerTransaction
join pt in ProductType on pt.ProductTypeId equals ct.ProductTypeId
join ss in Status on s.StatusId equals ct.StatusId
select new all fields
}
Models:
public class CustomerTransaction
{
public int CustomerTransactionId{ get; set; },
public int ProductTypeId {get; set; }, //joins to ProductTypeTable
public int StatusID {get; set; }, //joins to StatusTypeTable
public string DateOfPurchase{ get; set; },
public int PurchaseAmount { get; set; },
}
public class ProductType
{
public int ProductTypeId{ get; set; }
public string ProductName { get; set; },
public string ProductDescription { get; set; },
}
public class StatusType
{
public int StatusId{ get; set; }
public string StatusName{ get; set; },
public string Description{ get; set; },
}
One of the ways to establish One-To-Many Relationships in ASP.NET Core is the Fluent API
public class CustomerTransaction
{
public int CustomerTransactionId { get; set; }
public string DateOfPurchase{ get; set; }
public int PurchaseAmount { get; set; }
// relationships
public ProductType ProductType { get; set; }
public int ProductTypeId { get; set; }
public StatusType StatusType { get; set; }
public int StatusID { get; set; }
}
public class ProductType
{
public int ProductTypeId { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
// relationships
public ICollection<CustomerTransaction> CustomerTransactions { get; set; }
}
public class StatusType
{
public int StatusId { get; set; }
public string StatusName { get; set; }
public string Description { get; set; }
// relationships
public ICollection<CustomerTransaction> CustomerTransactions { get; set; }
}
Then simply use Include to properly join them together in your result.
public void GetByCustomerTransactionId(int id)
{
var result = context.CustomerTransaction.Where(x=>x.CustomerTransactionId == id)
.Include(i=>i.ProductType)
.Include(i=>i.StatusType);
}
Considering there are foreign key constraints on the tables, you can simply do this without having to do any joins yourself
public class CustomerTransaction
{
public int CustomerTransactionId{ get; set; },
public int ProductTypeId {get; set; }, //joins to ProductTypeTable
public int StatusID {get; set; }, //joins to StatusTypeTable
public string DateOfPurchase{ get; set; },
public int PurchaseAmount { get; set; },
// Add this
public ProductType ProductType { get; set;}
public StatusType StatusType { get; set;}
}
and then on your repository simply get the CustomerTransation and it will return the joined tables too, based on their foreign key
CustomerTransaction GetByCustomerTransactionId(int id)
{
var result = ct.CustomerTransaction.Where(x => x.CustomerTransactionId == id).ToList()
return result;
}
That will give you your CustomerTransactions, their StatusType and ProductType
I'm new in Asp.Net and Entity Framework and i have a little issue.
I know u can help me , because its simple and i only know how to do it in PHP XD
I Have 2 models
public class Suppliers
{
public int ID { get; set; }
public int ID_Guard { get; set; }
public string Supplier{ get; set; }
public string Description { get; set; }
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd hh:mm tt}", ApplyFormatInEditMode = true)]
public DateTime Enter { get; set; }
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd hh:mm tt}", ApplyFormatInEditMode = true)]
public DateTime Exit { get; set; }
public virtual Guard Guard { get; set; }
}
public class Guard
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Suppliers> Suppliers{ get; set; }
}
controller
public class SuppliersController : Controller
{
private SuppliersContext db = new SuppliersContext();
public ActionResult Index()
{
return View(db.Suppliers.ToList());
}
}
And i wanna pass to the view the 2 table data and relate it
When i go to index show me all the suppliers data and show the Guard name( the person who registered the supplier enter and exit)
Well its solved
var results = from c in db.Suppliers
join cn in db.Guard on c.ID_Guard equals cn.ID
where (c.ID_Guard == cn.ID)
select new Models.MyViewModel{ Name= cn.Name, ID = c.ID, Supplier=c.Supplier, Description=c.Description, Enter=c.Enter, Exit=c.Exit};
follow the below code it works and seems same like yours also i added the link hope you find It helpful
public class Product
{
public Product() { Id = Guid.NewGuid(); }
public Guid Id { get; set; }
public string ProductName { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
}
public class ProductCategory
{
public int Id { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
/////view model///
public class ProductViewModel
{
public Guid Id { get; set; }
[Required(ErrorMessage = "required")]
public string ProductName { get; set; }
public int SelectedValue { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
[DisplayName("Product Category")]
public virtual ICollection<ProductCategory> ProductCategories { get; set; }
}
follow the below tutorial
relationship model
for basic join use below query
var dealercontacts = from contact in table1
join table2 in table2 on contact.Id equals another.ID
select contact;
I've a model as described below:
public class Student
{
public int Id { get; set; }
public string Level { get; set; }
public string Subject { get; set; }
public string School { get; set; }
public int CityId { get; set; } //from City
}
public class City
{
public int Id { get; set; }
public string City { get; set; }
public int StateId { get; set; } //from State
}
public class State
{
public int Id { get; set; }
public string State { get; set; }
public int CountryId { get; set; } //from Country
}
public class Country
{
public int Id { get; set; }
public string Country { get; set; }
}
I wants to query the Student Entity and needs to include the Country (Only Country) to the student Model.
The Database structure is like as above, I cannot change the DB Table Structure.
But I can able to edit the EF Entities above. Ultimately I need the Student info with country as a Student Entity, So that I can draw jqGrid and sort them based on country too.
Well if you can't modify your entity classes to add the corresponding navigation properties, you can try this:
var query = from student in context.Students
join city in context.Cities on student.CityId equals city.Id
join state in context.States on city.StateId equals state.Id
join country in context.Countries on state.CountryId equals country.Id
select new {
StudentId=student.Id,
Level=student.Level,
...
Country=country.Country
};
Or maybe:
select new {Student=student, Country=country.Country};
If your tables are related, I suggest you include the navigation properties to your model:
public class Student
{
public int Id { get; set; }
//...
public int CityId { get; set; } //from City
public virtual City City{get;set;}
}
public class City
{
public int Id { get; set; }
//...
public int StateId { get; set; } //from State
public virtual City City{get;set;}
public virtual ICollection<Student> Students{get;set;}
}
public class State
{
public int Id { get; set; }
//...
public int CountryId { get; set; } //from Country
public virtual Country Country {get;set;}
public virtual ICollection<City> Cities{get;set;}
}
public class Country
{
public int Id { get; set; }
public string Country { get; set; }
public virtual ICollection<State> States{get;set;}
}
That is not going to affect your current DB schema. This way is more easy to reach to the country name using a student instance (as #SteveGreene show in his answer):
var countryName=student.City.State.Country.Country;
You can project that into an anonymous object or viewmodel:
var studentWithCountry = context.Student.Where(Id = myVar.Id)
.Select(s => new { Level = s.Level,
Subject = s.Subject,
...
Country = s.City.State.Country.Country });
I have two classes that partake in a parent-child relationship. The parent class is Country, and the child class is City:
public partial class Country
{
public Country()
{
this.Cities = new List<City>();
}
public int Id { get; set; }
public string Name { get; set; }
public string AlphaCodeTwo { get; set; }
public string AlphaCodeThree { get; set; }
public Nullable<int> NumericCode { get; set; }
public string Capital { get; set; }
public string Nationality { get; set; }
public Nullable<decimal> CapitalArea { get; set; }
public Nullable<decimal> CapitalPopulation { get; set; }
public string Image { get; set; }
public virtual List<City> Cities { get; set; }
}
public partial class City
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public Nullable<int> NumericCode { get; set; }
public virtual Country Country { get; set; }
}
When I select a City object with the following LINQ query, the navigation property to the parent class is null:
private List<Country> _Country;
var City = _Country.SelectMany(c => c.Cities).OrderBy(ci => ci.Name).ToList();
I get all children, but no parent data.
If you're using Entity Framework, you can use .Include() to grab the navigation property data as you load the objects. Note that it tends to produce some pretty gnarly queries.
var city = (
from c in db.Cities.Include(c => c.Country)
where c.CountryId == CountryId
orderby c.Name
select c
).ToList();