I cannot get the data from adc to update to database. I am using LINQ2SQL dbml.
I get no sql output from CAPcontext.Log, and Both tables have primary ID's
I feel it is an issue with the join in the LINQ query but couldnt find anything on the web regarding it. Can someone point out what am I doing wrong?
CAP_MDF_dataContextDataContext CAPcontext = new CAP_MDF_dataContextDataContext();
public bool LoadCAPadultdaycare()
{
CAPcontext.Log = Console.Out;
var adc = (from v in CAPcontext.AdultDayCares
join s in CAPcontext.States on v.state equals s.Name
select new CAPadultdaycare {
Avg = v.Avg,
City = v.city,
High = v.High,
Low = v.Low,
StateFullName = v.state,
StateAbbr = s.Code
}).ToList();
foreach (var item in adc)
{ item.City = "some city";
// updating more fields but omitted here
}
CAPcontext.SubmitChanges();
return true;
}
My CAPadultdaycare class is...
public class CAPadultdaycare
{
public decimal? High { get; set; }
public decimal? Low { get; set; }
public decimal? Avg { get; set; }
public string Zip { get; set; }
public string City { get; set; }
public string StateAbbr { get; set; }
public string StateFullName { get; set; }
}
You are creating new CAPadultdaycare objects, which are not attached to your data Context and hence not submitted.
The following may work
var adc = (from v in CAPcontext.AdultDayCares
join s in CAPcontext.States on v.state equals s.Name
select v).ToList();
foreach (var item in adc)
{ item.City = "some city";
// updating more fields but omitted here
}
CAPcontext.SubmitChanges();
but this means you are pulling all columns from your database.
Related
I'm stuck here on a situation wherein I should display the details of a person together with the list of his/her allocations. I've done creating a view model to pass the data to a view but the result is:
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[EKCMIDTA.ViewModels.EmployeeDetailsVM]', but this dictionary requires a model item of type 'EKCMIDTA.ViewModels.EmployeeDetailsVM'.
For the TicketScannings table, I just wanted to know whether the person has used some of the allocations, and to count how many were used, regardless it it's null.
I hope someone can help me with this.
Thanks!
Controller:
public ActionResult GetDetails(int empId)
{
var employeeInformation = identityContext.AspNetUsers.Find(empId);
var employeeDetails = dbContext.TicketAllocations.Include(a => a.AllocationCategory).Where(t => t.CMId == empId).ToList();
var query = (from alloc in dbContext.TicketAllocations
join scan in dbContext.TicketScannings
on alloc.Id equals scan.TicketAllocationId
join card in dbContext.CardNumberAssignments
on alloc.CMId equals card.CMId into a
from card in a.DefaultIfEmpty()
join reserve in dbContext.ReservedCardNumbers
on card.CardNumberId equals reserve.Id into b
from reserve in b.DefaultIfEmpty()
where (alloc.CMId == empId)
select new EmployeeDetailsVM()
{
Employee = new Employee()
{
FirstName = employeeInformation.FirstName,
LastName = employeeInformation.LastName,
CMId = employeeInformation.Id,
CardNumber = reserve == null ? "No Card Number yet" : reserve.CardNumber,
QRCode = card == null ? "No QR Code yet" : card.QRCode
},
GetTicketAllocations = employeeDetails
});
return View(query);
View Model:
public class EmployeeDetailsVM
{
public Employee Employee { get; set; }
public IEnumerable<Allocation> GetTicketAllocations { get; set; }
}
public class Employee
{
public string CMId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CardNumber { get; set; }
public string QRCode { get; set; }
}
public class Allocation
{
public int AllocationId { get; set; }
public string AllocationName { get; set; }
public int Quantity { get; set; }
public bool IsActive { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
}
View:
#model EKCMIDTA.ViewModels.EmployeeDetailsVM
Looks like your view is only accepting a model of a single EmployeeDetailsVM, but you're passing in a query which would could return multiple.
so you can change #model EKCMIDTA.ViewModels.EmployeeDetailsVM to #model IEnumerable<EKCMIDTA.ViewModels.EmployeeDetailsVM>
or change your GetDetails action to return View(query.FirstOrDefault());
Edit based on comment
public ActionResult GetDetails(int empId)
{
var employeeInformation = identityContext.AspNetUsers.Find(empId);
var employeeTickets = dbContext.TicketAllocations.Include(a => a.AllocationCategory).Where(t => t.CMId == empId).ToList();
var employeeDetails = (from alloc in dbContext.TicketAllocations
join scan in dbContext.TicketScannings
on alloc.Id equals scan.TicketAllocationId
join card in dbContext.CardNumberAssignments
on alloc.CMId equals card.CMId into a
from card in a.DefaultIfEmpty()
join reserve in dbContext.ReservedCardNumbers
on card.CardNumberId equals reserve.Id into b
from reserve in b.DefaultIfEmpty()
where (alloc.CMId == empId)
select new EmployeeDetailsVM()
{
Employee = new Employee()
{
FirstName = employeeInformation.FirstName,
LastName = employeeInformation.LastName,
CMId = employeeInformation.Id,
CardNumber = reserve == null ? "No Card Number yet" : reserve.CardNumber,
QRCode = card == null ? "No QR Code yet" : card.QRCode
}
}).FirstOrDefault();
if (employeeDetails != null)
employeeDetails.GetTicketAllocations = employeeTickets;
return View(employeeDetails);
}
ASPNET MVC5 web app
In getting Products, whose relation with other entities is described by following models, I need to filter only those Products.Category.CategoryTrans whose language_id equals the culture param.
Please note I need to pass the result as an IQueryable to subsequent paging and sorting methods, already implemented.
Models:
public partial class Product
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
public int CategoryID { get; set; }
public virtual Category Category { get; set; }
[NotMapped]
public virtual CategoryTrans CategoryTrans { get; set; }
}
public partial class Category
{
public int ID { get; set; }
public string Name { get; set; }
public int? ParentID { get; set; }
public bool IsDeleted { get; set; }
public virtual ICollection<Product> Products { get; set; }
public virtual ICollection<CategoryTrans> CategoryTrans { get; set; }
}
public class ISO_Languages
{
public int ID { get; set; }
public string code { get; set; }
public bool IsEnabled { get; set; }
public string name_en { get; set; }
public string name_fr { get; set; }
public string name_it { get; set; }
public string name_de { get; set; }
public string name_es { get; set; }
}
public class CategoryTrans
{
[Key, Column(Order = 1)]
public int category_id { get; set; }
[Key, Column(Order = 2)]
public int language_id { get; set; }
[ForeignKey("category_id")]
public virtual Category categoryId { get; set; }
[ForeignKey("language_id")]
public virtual ISO_Languages languageId { get; set; }
public string name { get; set; }
}
Following query returns ALL CategoryTrans in p.Category.CategoryTrans, that means any category translation
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = (from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select p);
return query;
}
What I am trying to do is filtering, for every product, the single category translation, depending on culture input parameter.
Something like:
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).SingleOrDefault()
};
return query;
}
but getting error:
The entity or complex type 'xyz.DAL.Product' cannot be constructed in a LINQ to Entities query.
Looking for this specific error I now tried projecting onto a DTO:
public class ProductDTO
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual CategoryTrans CategoryTrans { get; set; }
}
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select new ProductDTO
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).FirstOrDefault()
};
return query.Cast<Product>();
}
And that is now working as expected, returning only required translation to CategoryTrans.
So the query works now BUT casting ProductDTO to needed Product returns:
Unable to cast the type 'xyz.Controllers.ProductDTO' to type 'xyz.Models.Product'. LINQ to Entities only supports casting EDM primitive or enumeration types.
I cannot find a solution to this exception.
Even if you are able to cast ProductDTO to Product model, these objects will not be tracked automatically by EF.
One possible solution may be to first select the Products, then iterate over them to assign the required property.
In your first (failed) query, I believe teh select can be replaced with :
select new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = ct
};
which may work.
Otherwise, you cannot Cast<> from one object type to another unless they have a base/derived relationship. Otherwise, you'll need to convert them:
in Product DTO, add:
replace :
return query.Cast<Product>();
with:
return query.Select(p=> new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.CategoryTrans
};
UPDATE:
Ok, let's try something different. Drop the select from the query, and just use the p object:
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db,
string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture;
return query;
}
that will leave the CategoryTrans property null, but it will get you through this and the other manipulations of the query. When you get to the end, and are actually doing things with the result, then pull out the p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).FirstOrDefault() to get the CategoryTrans
I could not find an answer to the
The entity or complex type 'xyz.DAL.Product' cannot be constructed in a LINQ to Entities query.
error. I eventually solved the problem by adding a
[NotMapped]
public virtual string LocalizedCategoryName { get; set; }
to Product model Class, in charge for displaying localized category name, and moving the filtering to the ViewModel, setting two nested foreach loops, returning a new List of fully localized products:
private List<Product> _LocalizedProductList = new List<Product>();
public List<Product> LocalizedProductList
{
get
{
HttpUtilities HttpHelper = new HttpUtilities();
string culture = HttpHelper.getFullCulture();
int IsoCode = GenericUtilities.getIsoID(culture, db);
List<Product> localized = new List<Product>();
foreach (Product p in _LocalizedProductList)
{
foreach (CategoryTrans c in p.Category.CategoryTrans)
{
if (c.language_id.Equals(IsoCode))
{
Product x = new Product
{
ID = p.ID,
LocalizedCategoryName = c.name,
DateCreated = p.DateCreated,
DateExpire = p.DateExpire,
DateLastModified = p.DateLastModified,
Name = p.Name,
Description = p.Description,
IsApproved = p.IsApproved,
IsDeleted = p.IsDeleted,
ProductImages = p.ProductImages,
User = p.User
};
localized.Add(x);
};
}
}
return localized;
}
set { _LocalizedProductList = value; }
}
No idea if it's the best or the only way to do it, but works as intended. I can now stay with the simple query and pass the returned IQueryable of Product onto the sorting and paging async method or whatever. Whenever I am done, the result is being assigned to ViewModel.LocalizedProductList, where the getter takes care of the final filtering. Thanks to wonderbell for the suggestion that one possible solution could be to first select the Products, then iterate over them to assign the required property. That's why upvoted his/her post even it cannot be considered as a complete (or even partial) solution to the question.
I am new to Entity Framework 7 code-first and came across a mapping issue with stored procedure.
Below are two classes where cityid is the relational property:
public class CityList
{
[Key]
public int CityId { get; set; }
[Required]
[MaxLength(50)]
public string CityName { get; set; }
[MaxLength(200)]
public string CityDescription { get; set; }
public ICollection<PointOfInterestList> PointOfInterestList { get; set; } = new List<PointOfInterestList>();
}
public class PointOfInterestList
{
[Key]
public int PointsofInterestId { get; set; }
[Required]
[MaxLength(50)]
public string PointsofInterestName { get; set; }
[MaxLength(200)]
public string PointsofInterestDescription { get; set; }
[ForeignKey("CityId")]
public CityList CityList { get; set; }
public int CityId { get; set; }
}
Using DbContext to populate the CityList object from a stored procedure GetCity:
var returnlist = _context.CitiesList.FromSql("GetCity #p0", CityId).ToList();
Stored procedure code:
CREATE PROCEDURE [GetCity]
(#CityId INT = 0)
AS
BEGIN
IF #CityId = 0
SET #CityId = NULL
SELECT
c.Id CityId, C.Description CityDescription, C.Name CityName--,c.Country
,p.Id PointsofInterestId, p.Name PointsofInterestName, p.Description PointsofInterestDescription
FROM
dbo.Cities c
INNER JOIN
dbo.PointOfInterest p ON p.CityId = c.Id
WHERE
c.Id = ISNULL(#CityId, c.Id)
END
The stored procedure gets executed and populates the CityList collection, but the PointOfInterestList collection within each CityList object does not get mapped with the stored procedure result.
Let me know if I have missed any step.
When you map via a stored procedure, it isn't smart enough to know about any Includes are doing (since you can't do .Include(...)). It only knows the direct fields on the entity you are directly mapping to. Thus, the only way you'd be able to fix this is to create your own DTO that has both the header and lines in it and then have a custom map to push that data into the appropriate entities, along with having to deal with the duplicate header data yourself. (i.e. If you have 2 lines, you'd need 1 header and then add both lines to that header. Uniqueness based on PK would work.)
Edit - Example:
public class MyCustomRowDto
{
public int CityId { get; set; }
public string CityName { get; set; }
public string CityDescription { get; set; }
public int PointsofInterestId { get; set; }
public string PointsofInterestName { get; set; }
public string PointsofInterestDescription { get; set; }
}
Then when you call the stored procedure:
var list = context.Database.SqlQuery<MyCustomRowDto>("...").ToList();
Then you'll need some sort of mapping layer with a dictionary for the primary key. Something like this:
var data = new Dictionary<int, CityList>();
foreach (var item in list) {
CityList entity;
if (!data.TryGet(item.CityId, out entity)) {
entity = new CityList() { CityId = item.CityId, CityName = item.CityName ..., PointOfInterestList = new List<PointOfInterestList>() };
data.Add(item.CityId, entity);
}
entity.PointOfInterest.Add(new PointOfInterestList() { PointOfInterestId = item.PointofInterestId, ..., CityId = item.CityId, CityList = entity
}
return data.Select(a => a.Value).ToList();
I am trying to get a query that returns everything properly formatted for my ViewModel so I do not have to manually copy everything over from my entity models. I have this Linq query that is giving me an error. :
var query = from i in context.Invoices
join l in context.LineItems on i.InvoiceID equals l.InvoiceID into il
where i.InvoiceID == id
select new InvoiceViewModel()
{
InvoiceID = i.InvoiceID,
CustomerID = i.CustomerID,
InvoiceNote = i.Note,
InvoiceDate = i.InvoiceDate,
Terms = i.Terms,
LineItems = il.ToList<LineItemViewModel>()
};
This is my ViewModel
public class InvoiceViewModel {
public int InvoiceID { get; set; }
public int CustomerID { get; set; }
public string InvoiceNote { get; set; }
public DateTime InvoiceDate { get; set; }
public string Terms { get; set; }
public virtual ICollection<LineItemViewModel> LineItems { get; set; }
}
public class LineItemViewModel {
public int LineItemID { get; set; }
public int InvoiceID { get; set; }
public int Quantity { get; set; }
public string Item { get; set; }
public decimal Amount { get; set; }
public string LineItemNote { get; set; }
}
The error I am getting is (the red squigly is under the il in LineItems = il.ToList())
'IEnumerable<LineItem>' does not contain a definition for 'ToList' and the best extension method overload 'Enumerable.ToList<LineItemViewModel>(IEnumerable<LineItemViewModel>)' requires a receiver of type 'IEnumerable<LineItemViewModel>'
Which I (sorta, kinda, a little) understand. So what is the proper syntax for this?
You need to explicitly initialize your LineItemViewModel instances from the LineItem entities. You might be better off writing this as a correlated subquery rather than a join:
var query =
from i in context.Invoices
where i.InvoiceID == id
select new InvoiceViewModel()
{
InvoiceID = i.InvoiceID,
CustomerID = i.CustomerID,
InvoiceNote = i.Note,
InvoiceDate = i.InvoiceDate,
Terms = i.Terms,
LineItems =
(
from li in context.LineItems
where li.InvoiceID == i.InvoiceID
select new LineItemViewModel
{
LineItemID = li.LineItemID,
InvoiceID = li.InvoiceID,
Quantity = li.Quantity,
Item = li.Item,
Amount = li.Amount,
LineItemNote = li.LineItemNote,
}
).ToList()
};
I have two tables: tour and hotel I want to execute query with join and get the result in the View.
How to view data from two tables as figure below?
enter link description here
in the Controller I have this code :
public ActionResult DetailView(string strID)
{
var id_tour = (from data1 in _db.Tours
join dataview2 in _db.TypeOfCosts on data1.ID_TourCost equals dataview2.ID_TourCost
where (data1.ID_Tour == strID) && (data1.ID_TourCost == dataview2.ID_TourCost)
select new
{
data1.TourName,
data1.ID_Tour,
data1.DepartureDay,
data1.DeparturePosition,
data1.AvailableRoom,
dataview2.AdultCost,
dataview2.ChildrenCost,
dataview2.BabyCost,
}).FirstOrDefault();
var view_tour = new DetailModels(id_tour.TourName, id_tour.ID_Tour, Convert.ToDateTime(id_tour.DepartureDay), id_tour.DeparturePosition,
Convert.ToInt32(id_tour.AvailableRoom),
Convert.ToInt32(id_tour.AdultCost), Convert.ToInt32(id_tour.ChildrenCost), Convert.ToInt32(id_tour.BabyCost));
return View(view_tour);
}
[HttpPost]
public ActionResult DetailView(DetailModels model)
{
var id_hotel = from data2 in _db.Tours
join dataview3 in _db.TourPrograms on data2.ID_Tour equals dataview3.ID_Tour
join dataview4 in _db.Programs on dataview3.ID_TourProgram equals dataview4.ID_TourProgram
join dataview5 in _db.Hotels on dataview4.ID_Hotel equals dataview5.ID_Hotel
where (data2.ID_Tour == dataview3.ID_Tour) &&
(dataview3.ID_TourProgram == dataview4.ID_TourProgram) && (dataview4.ID_Hotel == dataview5.ID_Hotel)
select new
{
dataview5.HotelName,
dataview5.HotelAddress,
dataview5.HotelPhoneNumber,
};
// chuyền dữ liệu vào như thế nào
return RedirectToAction("DetailView", "Tourpackage");
}
in the Model I have this code:
enter code here public class DetailModels
{
public string TourName { get; set; }
public string ID_Tour { get; set; }
public DateTime DepartureDay { get; set; }
public string DeparturePosition { get; set; }
public int AvailableRoom { get; set; }
public string HotelName { get; set; }
public string HotelAddress { get; set; }
public int HotelPhoneNumber { get; set; }
public int AdultCost { get; set; }
public int ChildrenCost { get; set; }
public int BabyCost { get; set; }
public DetailModels(string tourname, string idtour, DateTime dapartureday, string departureposition, int availableroom,
int adultcost, int childrencost, int babycost)
{
this.TourName = tourname; this.ID_Tour = idtour; this.DepartureDay = dapartureday; this.DeparturePosition = departureposition;
this.AvailableRoom = availableroom;
this.AdultCost = adultcost; this.ChildrenCost = childrencost; this.BabyCost = babycost;
}
hope to the help of everyone............thanks
When You are using MVC i strongly recommend You to use Entity Framework. If You never use it check this out: http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=aspdotnet-mvc3-intro - very good video-tutorial.
I assume that Tour-Hotel relation is typical many-to-many. Mapped by EF class Tour will have property Hotels and vice versa. If You pass for example Tour to view #Model.Hotels give You collection of related hotels. And BTW do some refactoring code,please:)