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());
Currently, I can insert a record which contains the second, minute, hour, Repeat, JobId and UserID, however, it will only insert one value from each of the List<object>.
Question 1:
How do I add values from a List<object> (model.DayOfMonth, model.Month and model.DaysOfWeek) into the local database?
Question 2:
Also, to my understanding, each value in the list should have their own record. How would I create a new record for each value in the List<object> (named above) while copying over the same second, minute, hour, repeat, JobId and UserID.
Controller:
[HttpPost]
public ActionResult ScheduleInfo(Values model, int JobList1, string Second, string Minute, string Hour, object DayOfMonth, object Month, object DaysOfWeek, int repeatTime)
{
var secondCon = Convert.ToInt32(Second);
var minuteCon = Convert.ToInt32(Minute);
var hourCon = Convert.ToInt32(Hour);
model.Job = JobList1;
model.Second = secondCon;
model.Minute = minuteCon;
model.Hour = hourCon;
model.DayOfMonth = new List<object>();
model.Month= new List<object>();
model.DaysOfWeek = new List<object>();
foreach (var dofm in model.DofMInfo)
{
if (dofm.IsChecked)
{
model.DayOfMonth.Add(dofm.DofMID);
}
}
foreach (var month in model.MonthInfo)
{
if (month.IsChecked)
{
model.Month.Add(month.monthID);
}
}
foreach (var day in model.DayInfo)
{
if (day.IsChecked)
{
model.DaysOfWeek.Add(day.dayID);
}
}
model.repeatTime = repeatTime;
try
{
ScheduleEntity db = new ScheduleEntity();
AspNetUser aspNetUser = new AspNetUser();
Job job = new Job();
Schedule sched = new Schedule();
sched.Second = Convert.ToString(model.Second);
sched.Minute = Convert.ToString(model.Minute);
sched.Hour = Convert.ToString(model.Hour);
//foreach (var day in model.DayOfMonth)
//{
// sched.DayOfMonth = Convert.ToString(day);
//}
//foreach (var month in model.Month)
//{
// sched.Month = Convert.ToString(month);
//}
//foreach (var weekday in model.DaysOfWeek)
//{
// sched.DayOfWeek = Convert.ToString(weekday);
//}
sched.Repeat = 4;
sched.JobId = 2;
sched.AspNetUsersId = User.Identity.GetUserId();
db.Schedules.Add(sched);
db.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
return RedirectToAction("SchedulerIndex");
}
}
The Schedule class I'm calling and setting as sched:
using System;
using System.Collections.Generic;
public partial class Schedule
{
public int ScheduleID { get; set; }
public string Second { get; set; }
public string Minute { get; set; }
public string Hour { get; set; }
public string DayOfMonth { get; set; }
public string Month { get; set; }
public string DayOfWeek { get; set; }
public string AspNetUsersId { get; set; }
public Nullable<int> JobId { get; set; }
public int Repeat { get; set; }
public virtual AspNetUser AspNetUser { get; set; }
public virtual Job Job { get; set; }
}
This question already has answers here:
SQLite .NET performance, how to speed up things?
(2 answers)
Closed 7 years ago.
I am having a hard time trying to save the data faster, to a local DB.
Even though this is a one time saving, when the app runs for the first time, it takes like 90 seconds, in a Lumia 920, to save "only" the "map tables".
What I do:
1) I call an API, where I receive all the grids, with its Xs, Ys, Map Id, etc.
2) I deserialize the info based on a class I have defined.
3) For each item, in that info, I save the "misc" info (since I will use it)
4) I save, in a GRIDS table, each grid inside the previous item.
This code snipet is what I use to deserialize the info, and call the function to save in the DB
public class Maps
{
public string id { get; set; }
public string name { get; set; }
public string height { get; set; }
public string width { get; set; }
public string tile { get; set; }
public string shopping_id { get; set; }
public string url { get; set; }
public string updated_at { get; set; }
public string created_at { get; set; }
public GridFirst gridFirst { get; set; }
public GridLast gridLast { get; set; }
public List<Grid> grid { get; set; }
public class GridFirst
{
public string id { get; set; }
public string x { get; set; }
public string y { get; set; }
public string maps_id { get; set; }
public string value { get; set; }
}
public class GridLast
{
public string id { get; set; }
public string x { get; set; }
public string y { get; set; }
public string maps_id { get; set; }
public string value { get; set; }
}
public class Grid
{
public string id { get; set; }
public string x { get; set; }
public string y { get; set; }
public string maps_id { get; set; }
public string value { get; set; }
}
public void deserializeAndConvert(string aaa)
{
JObject myGeneral = JObject.Parse(aaa);
IList<JToken> results = myGeneral["resp"].Children().ToList();
// serialize JSON results into .NET objects
IList<Maps> searchResults = new List<Maps>();
foreach (JToken result in results)
{
Maps searchResult = JsonConvert.DeserializeObject<Maps>(result.ToString());
searchResults.Add(searchResult);
}
var respuesta = from data in searchResults
select new
{
id = data.id,
name = data.name,
height = data.height,
width = data.width,
tile = data.tile,
url = data.url,
lastX = data.gridLast.x,
lastY = data.gridLast.y,
grid = data.grid
};
foreach (var a in respuesta)
{
Database_Controller.getReadyToSaveData("mapinfo", 8, a.id, a.name, a.height, a.width, a.tile, a.url, a.lastX, a.lastY, "", "", "", "", "", "", "");
foreach (var data in a.grid)
{
Database_Controller.getReadyToSaveData("mapgrid", 5, data.id, data.x, data.y, data.maps_id, data.value, "", "", "", "", "", "", "", "", "", "");
}
}
}
}
And these are the functions that save the data, in the DB
public static void getReadyToSaveData(string dbName, int numberOfParams, string param1, string param2, string param3, string param4, string param5, string param6, string param7, string param8, string param9, string param10, string param11, string param12, string param13, string param14, string param15)
{
List<string> myParams = new List<string>();
myParams.Add(param1);
myParams.Add(param2);
myParams.Add(param3);
myParams.Add(param4);
myParams.Add(param5);
myParams.Add(param6);
myParams.Add(param7);
myParams.Add(param8);
myParams.Add(param9);
myParams.Add(param10);
myParams.Add(param11);
myParams.Add(param12);
myParams.Add(param13);
myParams.Add(param14);
myParams.Add(param15);
List<string> myParamsToDB = new List<string>();
for (var i = 0; i < numberOfParams; i++)
{
myParamsToDB.Add(myParams[i]);
}
insertData(dbName, myParamsToDB);
}
public static void insertData(string dbName, List<string> paramsToGo)
{
try
{
using (var connection = new SQLiteConnection("Unicenter.sqlite"))
{
if (dbName == "mapgrid")
{
using (var statement = connection.Prepare(#"INSERT INTO mapgrid (ID,X,Y,MAPS_ID,VALUE)
VALUES(?, ?,?,?,?);"))
{
statement.Bind(1, paramsToGo[0]);
statement.Bind(2, paramsToGo[1]);
statement.Bind(3, paramsToGo[2]);
statement.Bind(4, paramsToGo[3]);
statement.Bind(5, paramsToGo[4]);
// Inserts data.
statement.Step();
statement.Reset();
statement.ClearBindings();
}
}
if (dbName == "mapinfo")
{
using (var statement = connection.Prepare(#"INSERT INTO mapinfo (ID,NAME,HEIGHT,WIDTH,TILE,URL,LASTX,LASTY)
VALUES(?, ?,?,?,?,?,?,?);"))
{
statement.Bind(1, paramsToGo[0]);
statement.Bind(2, paramsToGo[1]);
statement.Bind(3, paramsToGo[2]);
statement.Bind(4, paramsToGo[3]);
statement.Bind(5, paramsToGo[4]);
statement.Bind(6, paramsToGo[5]);
statement.Bind(7, paramsToGo[6]);
statement.Bind(8, paramsToGo[7]);
// Inserts data.
statement.Step();
statement.Reset();
statement.ClearBindings();
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception\n" + ex.ToString());
}
}
***Edit: As a kind reminder, in case some people does not see the tags (and mark this question as duplicated), this is FOR WINDOWS PHONE 8.1, so, the functions, references and classes ARE different from plain c#
Any idea on how to make it faster? ... What am I doing wrong?
you can use parallel.for loop which is more faster if you have large data or you can easily check each loop how much time it takes to execute in VS-2015
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