I'm new to asp.net mvc & I'm trying to make a website with asp.net mvc 4 & EF6 where user can sort a table after login. I'm getting a compile error saying Cannot implicitly convert type System.Linq.IQueryable to System.Collections.Generic.ICollection. My codes are below,
Controller
public ActionResult Login(string sortOrder)
{
if (Session["UserNAME"] != null)
{
ViewBag.CodeSort = String.IsNullOrEmpty(sortOrder) ? "code_desc" : "";
var sortedOut = new MkistatVsUserLogin { mkistats = dsedb.mkistats.AsQueryable() }; //Error in this line
switch (sortOrder)
{
case "code_desc":
sortedOut = sortedOut.OrderByDescending(s => s.MKISTAT_CODE);
break;
default:
sortedOut = sortedOut.OrderBy(s => s.MKISTAT_CODE);
break;
}
return View(sortedOut.ToList());
}
else
{
return RedirectToAction("Home");
}
}
Model
public class MkistatVsUserLogin
{
public mkistat mkistats { get; set; }
public idx Idxs { get; set; }
}
How can I solve this problem. Need this help badly. Tnx.
UPDATES
Mkistat Model
public partial class mkistat
{
public string MKISTAT_CODE { get; set; }
public int MKISTAT_NUMBER { get; set; }
public string MKISTAT_QUOTE_BASES { get; set; }
public decimal MKISTAT_OPEN_PRICE { get; set; }
public decimal MKISTAT_HIGH_PRICE { get; set; }
public decimal MKISTAT_LOW_PRICE { get; set; }
public decimal MKISTAT_SPOT_TOTAL_VALUE { get; set; }
public string MKISTAT_LM_DATE_TIME { get; set; }
}
You need to modify your model and set mkistats type to IQueryable<mkistat> , you are passing IQueryable<mkistat> where your property is of Type mkistat not IQueryable<mkistat>, you have to do like this:
public class MkistatVsUserLogin
{
public IQueryable<mkistat> mkistats { get; set; }
public idx Idxs { get; set; }
}
and now in your action:
var sortedOut = new MkistatVsUserLogin
{
mkistats = dsedb.mkistats.AsQueryable();
};
If you want to do with List<mkistat> htne your model should be like:
public class MkistatVsUserLogin
{
public List<mkistat> mkistats { get; set; }
public idx Idxs { get; set; }
}
and in action:
var sortedOut = new MkistatVsUserLogin
{
mkistats = dsedb.mkistats.ToList();
};
Apparently mkistats are implementing I generic collection, and by calling .AsQueryable() you are making an iQueryable collection. If you need it to be queryable, change mkistats to implement iQueryable.
Otherwise you can call .toList() on it, but you lose queryable support and lazy loading, if those are important.
Edit: It looks like you don't need queryable, so just do this:
var sortedOut = new MkistatVsUserLogin { mkistats = dsedb.mkistats.AsQueryable().toList() };
Likely you could also just leave both the .AsQueryable() and the .toList(). But it doesn't really matter and I can't decipher how your code fits together.
Related
I have a class MechanicalData and in that i have list of objects and in the below function i am trying to form list of objects with values coming from input.
Mechanicaldata class looks like below
public class MechanicalData
{
public List<LibraryA170> AirflowsA170 { get; set; }
......
}
and the classes libraryA170 and LibraryAcoustic looks like as follows
public class LibraryA170 : AEIMasterBase
{
public string Category { get; set; }
public string SpaceFunction { get; set; }
[Column(TypeName = "varchar(32)")]
public DirectExhaust? DirectExhaust { get; set; }
.....
......
}
public class LibraryAcoustic : AEIMasterBase
{
public string Category { get; set; }
public string SpaceFunction { get; set; }
public double? NoiseCriteria { get; set; }
.......
}
and base class AEIMasterBase looks like as below
public class AEIMasterBase
{
public Guid Id { get; set; }
public MasterSection MasterSection { get; set; }
public List<string> NotesHTML { get; set; }
public bool? IsApproved { get; set; }
public Guid? InitialRevisionId { get; set; }
public Guid? LatestRevisionId { get; set; }
public int? Revision { get; set; }
}
Below i am trying to map all those fields with LINQ select
private static MechanicalData TransformedMechanicalData(MechanicalData sourceMechanicalData, Dictionary<string, MasterSection> masterSectionMappedLibrary)
{
return new MechanicalData
{
AirflowsA170 = sourceMechanicalData.AirflowsA170.Select(airflow170 => new LibraryA170
{
Id = airflow170.Id,
InitialRevisionId = airflow170.InitialRevisionId,
LatestRevisionId = airflow170.LatestRevisionId,
IsApproved = true,
Revision = airflow170.Revision,
NotesHTML = airflow170.NotesHTML,
SpaceFunction = airflow170.SpaceFunction,
Category = airflow170.Category,
MasterSection = masterSectionMappedLibrary["Library A170"],
........
}).ToList(),
Acoustic = sourceMechanicalData.Acoustic.Select(acoustic => new LibraryAcoustic
{
Id = acoustic.Id,
InitialRevisionId = acoustic.InitialRevisionId,
LatestRevisionId = acoustic.LatestRevisionId,
IsApproved = true,
Revision = acoustic.Revision,
NotesHTML = acoustic.NotesHTML,
Category = acoustic.Category,
SpaceFunction = acoustic.SpaceFunction,
......
}).ToList()
};
}
is there any way i can pass two objects to a method and map common properties inside that method and leave uncommon properties to be mapped inside the select statement while adding to the list.
I am looking for something like as below if possible
public static class ItemExtensionMethods
{
public static readonly Expression<Func<Item, MinimalItem>> MapToMinimalItemExpr =
source => new MinimalItem
{
Id = source.Id, // only common properties like id, revision, IsApproved
Property1 = source.Property1
};
}
below are some common properties
Id = airflow170.Id,
InitialRevisionId = airflow170.InitialRevisionId,
LatestRevisionId = airflow170.LatestRevisionId,
.......
Could any one please suggest any idea on this, Many thanks in advance
update getting below error
Given two expression tree's, you want to locate the two MemberInitExpression nodes, merge their MemberBinding's and swap any ParameterExpression.
class LocateBindings : ExpressionVisitor
{
public IEnumerable<MemberBinding> Bindings { get; private set; }
protected override Expression VisitMemberInit(MemberInitExpression node)
{
Bindings = node.Bindings;
return base.VisitMemberInit(node);
}
}
class MergeBindings : ExpressionVisitor
{
private IEnumerable<MemberBinding> bindings;
private ParameterExpression parameter;
public MergeBindings(IEnumerable<MemberBinding> bindings, ParameterExpression parameter)
{
this.bindings = bindings;
this.parameter = parameter;
}
protected override Expression VisitMemberInit(MemberInitExpression node)
=> node.Update(node.NewExpression,
node.Bindings.Concat(bindings)
.Select(VisitMemberBinding));
protected override Expression VisitParameter(ParameterExpression node)
=> parameter;
}
public static Expression<Func<P, D>> Merge<BP, P, B, D>(
Expression<Func<BP, B>> baseExpr,
Expression<Func<P, D>> derivedExpr
)
where D:B where P:BP
{
var locate = new LocateBindings();
locate.Visit(baseExpr);
var merge = new MergeBindings(locate.Bindings, derivedExpr.Parameters[0]);
return merge.VisitAndConvert(derivedExpr, "");
}
For example;
Expression<Func<[insert type], AEIMasterBase>> baseExpression = basearg => new AEIMasterBase
{
Id = basearg.Id,
InitialRevisionId = basearg.InitialRevisionId,
LatestRevisionId = basearg.LatestRevisionId,
IsApproved = true,
Revision = basearg.Revision,
NotesHTML = basearg.NotesHTML,
SpaceFunction = basearg.SpaceFunction,
};
Expression<Func<[insert type], LibraryA170>> derivedExpression = airflow170 => new LibraryA170
{
Category = airflow170.Category,
MasterSection = masterSectionMappedLibrary["Library A170"],
};
var merged = Merge(baseExpression, derivedExpression);
...
AirflowsA170 = sourceMechanicalData.AirflowsA170.Select(merged).ToList()
...
I use AutoMapper 8.1.0 in a asp.net core project. I have an Automapper mapping that doesn't work as I expected. I reproduced the configuration so you can test it by yourself. So I have an ExpenseReport with a collection of ExpenseReportItem and this one with another collection. I have to keep the data of eTaxCollection after the mapping, but they are lost in the process.
So the question is why values of eTaxCollections are lost after calling _mapper.Map(vmodel, model) and how can I keep them?
The ignore attribute don't work. I also tried UseDestinationValue(). I lost 2 days trying to figure it out and I'm exhausted.
public void WeatherForecasts()
{
int[] excludeTaxes = new int[] { 2 };
var vmodel = new ExpenseReportCreateEditModel();
vmodel.Expenses.Add(new ExpenseReportItemModel()
{
ExcludeTaxIds = excludeTaxes,
Total = 12,
Id = 1
});
// fetch from bd
var model = new ExpenseReport();
// values will be lost after _mapper.Map...
var eTaxCollections = new HashSet<ExcludeExpenseReportItemTax>();
eTaxCollections.Add(new ExcludeExpenseReportItemTax()
{
TaxId = 1,
ExpenseReportItemId = 1
});
model.Items.Add(new ExpenseReportItem()
{
ExcludeTaxes = eTaxCollections,
ExpenseReportId = 1,
Id = 9
});
_mapper.Map(vmodel, model);
}
public class ExpenseReportCreateEditModelProfile : Profile
{
public ExpenseReportCreateEditModelProfile()
{
CreateMap<ExpenseReportCreateEditModel, ExpenseReport>()
.ForMember(d => d.Items, s => s.MapFrom(m => m.Expenses));
}
}
public class ExpenseReportItemModelProfile : Profile
{
public ExpenseReportItemModelProfile()
{
CreateMap<ExpenseReportItemModel, ExpenseReportItem>()
.ForMember(d => d.ExcludeTaxes, s => s.Ignore()); // <<<==== data are lost
}
}
public class ExpenseReportCreateEditModel
{
public int Id { get; set; }
public ICollection<ExpenseReportItemModel> Expenses { get; set; }
public ExpenseReportCreateEditModel()
{
Expenses = new HashSet<ExpenseReportItemModel>();
}
}
public class ExpenseReportItemModel
{
public int Id { get; set; }
public ICollection<int> ExcludeTaxIds { get; set; }
public decimal Total { get; set; }
public ExpenseReportItemModel()
{
ExcludeTaxIds = new HashSet<int>();
}
}
public class ExpenseReport
{
public int Id { get; set; }
public virtual ICollection<ExpenseReportItem> Items { get; set; }
public ExpenseReport()
{
Items = new HashSet<ExpenseReportItem>();
}
}
public class ExpenseReportItem
{
public int Id { get; set; }
public int ExpenseReportId { get; set; }
public virtual ICollection<ExcludeExpenseReportItemTax> ExcludeTaxes { get; set; }
public ExpenseReportItem()
{
ExcludeTaxes = new HashSet<ExcludeExpenseReportItemTax>();
}
}
public class ExcludeExpenseReportItemTax
{
public int ExpenseReportItemId { get; set; }
public virtual ExpenseReportItem ExpenseReportItem { get; set; }
public int TaxId { get; set; }
}
Thank you for any help
Edit
I execute the execution plan and perhaps this is the problem:
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
This is only way I can lost the values.
I have to find a solution now
Here the complete execution plan :
.If ($src == null) {
.Default(WebApplication1.Controllers.SampleDataController+ExpenseReportItem)
} .Else {
.Block() {
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
.Try {
.Block(System.Int32 $resolvedValue) {
.Block() {
$resolvedValue = .If (
$src == null || False
) {
.Default(System.Int32)
} .Else {
$src.Id
};
$typeMapDestination.Id = $resolvedValue
}
}
} .Catch (System.Exception $ex) {
.Block() {
.Throw .New AutoMapper.AutoMapperMappingException(
"Error mapping types.",
$ex,
.Constant<AutoMapper.TypePair>(AutoMapper.TypePair),
.Constant<AutoMapper.TypeMap>(AutoMapper.TypeMap),
.Constant<AutoMapper.PropertyMap>(AutoMapper.PropertyMap));
.Default(System.Int32)
}
};
$typeMapDestination
}
}
Trying to populate an ObservableCollection from a database using the Entity Framework. Everything was fine until I started working with linked tables.
I created the DeviceCategory and DeviceComplexity model, and now in the WyeModel I try to integrate them into the DeviceCategoryViewModel. Further, in DeviceCategoryViewModel, I indicated a request for taking information from the database, but I ran into a problem. How to fill in ObservableCollection with this information? I tried different ways, but it didn’t lead to anything, I just got more confused.
DeviceCategoriesViewModel
class DeviceCategoryViewModel
{
TechDContext dc = new TechDContext();
public int Device_category_id { get; set; }
public string Device_category_name { get; set; }
public int Device_complexity_id { get; set; }
public string Device_complexity_name { get; set; }
public static DeviceCategoryViewModel DeviceCaterogyVM(DeviceCategory deviceCategory, DeviceComplexity deviceComplexity)
{
return new DeviceCategoryViewModel
{
Device_category_id = deviceCategory.Device_category_id,
Device_category_name = deviceCategory.Category_name,
Device_complexity_id = deviceCategory.Device_complexity_id,
Device_complexity_name = deviceComplexity.Device_complexity_name
};
}
public void FillDeviceDategories()
{
var q = from cat in dc.DeviceCategories
join com in dc.DeviceComplexities on cat.Device_complexity_id equals com.Device_complexity_id
select new
{
Device_category_id = cat.Device_category_id,
Category_name = cat.Category_name,
Device_complexity_id = com.Device_complexity_id,
Device_complexity_name = com.Device_complexity_name
};
items = q;
deviceCategories = Convert(items);
}
public ObservableCollection<DeviceCategoryViewModel>
Convert(IEnumerable<object> original)
{
return new ObservableCollection<DeviceCategoryViewModel>(original.Cast<DeviceCategoryViewModel>());
}
private IEnumerable<object> items;
public IEnumerable<object> Items
{
get
{
return items;
}
}
private ObservableCollection<DeviceCategoryViewModel> deviceCategories;
public ObservableCollection<DeviceCategoryViewModel> DeviceCategories
{
get
{
FillDeviceDategories();
return deviceCategories;
}
}
DeviceCategory Model
[Table("device_categories")]
public class DeviceCategory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Device_category_id { get; set; }
public string Category_name { get; set; }
//[ForeignKey]
public int Device_complexity_id { get; set; }
public DeviceCategory()
{
}
public DeviceCategory(string name, int complexity_id)
{
Category_name = name;
Device_complexity_id = complexity_id;
}
}
DeviceCompexity Model
[Table("device_complexities")]
public class DeviceComplexity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Device_complexity_id { get; set; }
public string Device_complexity_name { get; set; }
public DeviceComplexity()
{
}
public DeviceComplexity(string name)
{
Device_complexity_name = name;
}
}
I now get an error in the conversion method
You'd try to cast your LINQ query result to ObservableCollection<DeviceCategoryViewModel> in separate Convert function.
Why not to directly collect your LINQ query result to ObservableCollection<DeviceCategoryViewModel>
Just use like this
var q = from cat in dc.DeviceCategories
join com in dc.DeviceComplexities on cat.Device_complexity_id equals com.Device_complexity_id
select new DeviceCategoryViewModel // <= Note This Line
{
Device_category_id = cat.Device_category_id,
Category_name = cat.Category_name,
Device_complexity_id = com.Device_complexity_id,
Device_complexity_name = com.Device_complexity_name
};
deviceCategories = new ObservableCollection<DeviceCategoryViewModel>(q);
OR if you want to get result after list then simply use q.ToList()
deviceCategories = new ObservableCollection<DeviceCategoryViewModel>(q.ToList());
In my controller I'm looping through items and saving them to my db. The problem is that it saves the first item, but none of the others. I put a breakpoint on the "SaveItem()" line in the loop and it hits it every time, but what seems odd to me is that it only goes through to the method for the 1st item.
What am I doing wrong?
public void SubmitItem(Cart cart, ShippingDetails shippingDetails, ProcessedItems processedItem, string orderID)
{
var cartItems = cart.Lines;
//CartIndexViewModel cartIndex = new CartIndexViewModel();
//var customID = cartIndex.OrderID;
foreach(var item in cartItems)
{
processedItem.OrderID = orderID;
processedItem.ProductID = item.Product.ProductID;
processedItem.Name = item.Product.Name;
processedItem.Description = item.Product.Description;
processedItem.Price = item.Product.Price;
processedItem.Category = item.Product.Category;
processedItem.ImageName = item.Product.ImageName;
processedItem.Image2Name = item.Product.Image2Name;
processedItem.Image3Name = item.Product.Image3Name;
processedItem.BuyerName = shippingDetails.Name;
processedItem.Line1 = shippingDetails.Line1;
processedItem.Line2 = shippingDetails.Line2;
processedItem.Line3 = shippingDetails.Line3;
processedItem.City = shippingDetails.City;
processedItem.State = shippingDetails.State;
processedItem.Zip = shippingDetails.Zip;
processedItem.Country = shippingDetails.Country;
processedItem.Status = "Submitted";
processedItems.SaveItem(processedItem);
}
}
public class EFProcessedItemsRepository : IProcessedItems
{
private EFDbContext context = new EFDbContext();
public IQueryable<ProcessedItems> ProcessedItem
{
get { return context.ProcessedItems; }
}
public void SaveItem(ProcessedItems processedItem)
{
if(processedItem.ProcessedID == 0)
{
try
{
context.ProcessedItems.Add(processedItem);
context.SaveChanges();
}
catch (Exception)
{
throw;
}
}
else
{
context.Entry(processedItem).State = EntityState.Modified;
}
}
public void DeleteItem(ProcessedItems processedItem)
{
context.ProcessedItems.Remove(processedItem);
context.SaveChanges();
}
}
here is the class for the processedItem:
public class ProcessedItems
{
[Key]
public int ProcessedID { get; set; }
public string OrderID { get; set; }
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public string ImageName { get; set; }
public string Image2Name { get; set; }
public string Image3Name { get; set; }
public string Status { get; set; }
//shipping
public string BuyerName { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Country { get; set; }
}
Interface:
public interface IProcessedItems
{
IQueryable<ProcessedItems> ProcessedItem { get; }
void SaveItem(ProcessedItems processedItem);
void DeleteItem(ProcessedItems processedItem);
}
try calling context.SaveChanges() after adding all of the items, I think it should persist them all in one go.
Another thing to try:
Refactor your code so that SaveItem accepts only one item to save, Add it and call SaveChanges()
Loop through the cart items outside the method and call the method with one item to save at a time.
// set orderID, shippingDetails above
foreach(var item in cartItems)
{
ProcessedItems processedItem = new ProcessedItems();
processedItem.OrderID = orderID;
processedItem.ProductID = item.Product.ProductID;
processedItem.Name = item.Product.Name;
processedItem.Description = item.Product.Description;
processedItem.Price = item.Product.Price;
processedItem.Category = item.Product.Category;
processedItem.ImageName = item.Product.ImageName;
processedItem.Image2Name = item.Product.Image2Name;
processedItem.Image3Name = item.Product.Image3Name;
processedItem.BuyerName = shippingDetails.Name;
processedItem.Line1 = shippingDetails.Line1;
processedItem.Line2 = shippingDetails.Line2;
processedItem.Line3 = shippingDetails.Line3;
processedItem.City = shippingDetails.City;
processedItem.State = shippingDetails.State;
processedItem.Zip = shippingDetails.Zip;
processedItem.Country = shippingDetails.Country;
SubmitItem(processedItem);
}
public void SubmitItem(ProcessedItems processedItem)
{
processedItem.Status = "Submitted";
processedItems.SaveItem(processedItem);
}
I think it is because processedItem is the same instance for each loop iteration. So after it has been through SaveItem once, it has its ProcessedID set and therefore won't get processed again.
My first guess is that you always store one entity, which is stored in processedItem, which is a input parameter. Try to create new Entity on each loop and then save it. In other words, you assign values to input parameter
processedItem.OrderID = orderID;
and then store same entity each time, but with changed fields
processedItems.SaveItem(processedItem);
I am using a repository class with linq-to-sql as the objectdatasource for a (web) GridView. The GridView has to allow sorting on all columns. I have a working solution using this approach but I would obviously prefer to do this without a predefined list of sort expressions.
public class TrailerMovementRepository
{
private TrailerMovementDataContext db = new TrailerMovementDataContext();
public IOrderedEnumerable<TrailerMovementHistory> GetTrailerMovementHistoryByDepotAndDate(string depot, DateTime searchDate, string sortExpression)
{
var unorderedQuery = (from tm in db.TrailerMovements
where tm.Depot == depot && tm.Date_In == searchDate && tm.Time_Out != null
select new TrailerMovementHistory
{
Depot = tm.Depot,
TrailerNumber = tm.Trailer,
TimeIn = tm.Time_In,
TimeOut = tm.Time_Out,
VOR = tm.VOR.Value,
Contents = tm.Contents,
Supplier = tm.Supplier,
TurnaroundTime = FormatDuration(tm.Time_Out - tm.Time_In),
VORTime = FormatDuration(tm.VOnR_Date - tm.VOffR_Date),
LoadedTime = tm.LoadedTime,
Destination = tm.Destination
}).ToList<TrailerMovementHistory>();
//need to find a way to dynamically do this from the passed in expression
IOrderedEnumerable<TrailerMovementHistory> orderedQuery = unorderedQuery.OrderBy(t => t.TrailerNumber);
switch (sortExpression)
{
case "TrailerNumber DESC":
orderedQuery = unorderedQuery.OrderByDescending(t => t.TrailerNumber);
break;
case "TimeIn":
orderedQuery = unorderedQuery.OrderBy(t => t.TimeIn);
break;
case "TimeIn DESC":
orderedQuery = unorderedQuery.OrderByDescending(t => t.TimeIn);
break;
...etc...
default:
break;
}
return orderedQuery;
}
public class TrailerMovementHistory
{
public TrailerMovementHistory()
{ }
public String Depot { get; set; }
public String TrailerNumber { get; set; }
public DateTime? TimeIn { get; set; }
public DateTime? TimeOut { get; set; }
public Boolean VOR { get; set; }
public String Contents { get; set; }
public String Supplier { get; set; }
public String TurnaroundTime { get; set; }
public String VORTime { get; set; }
public DateTime? LoadedTime { get; set; }
public String Destination { get; set; }
}
}
You might want to check out: SO