Casting collection from one db table to add to another db table - asp.net-mvc

Below is a chunk of my ActionMethod. The part I'm struggling with is casting a new variable integers with all IntegerBufferValues from db.IntegerBuffers and then adding them to db.IntegerList.
var integers = new ICollection<Integers>();
const int COUNT = 1000000;
Stopwatch watch = Stopwatch.StartNew();
for (int c = 0; c < COUNT; c++)
{
integers = db.IntegerBuffers.OrderBy(i => i.IntegerBufferValue);
};
watch.Stop();
var integerList = new IntegerList
{
Direction = direction,
Performance = watch.ElapsedMilliseconds,
Integers = integers
};
db.IntegerLists.Add(integerList);
IntegerList
namespace Project.Models
{
public class IntegerList
{
public int IntegerListID { get; set; }
public string Direction { get; set; }
public long Performance { get; set; }
public virtual ICollection<Integer> Integers { get; set; }
}
}
IntegerBuffer
namespace Project.Models
{
public class IntegerBuffer
{
public int IntegerBufferID { get; set; }
public int IntegerBufferValue { get; set; }
}
}
Edit: To show Integer class.
Integer
namespace IntegerSorterApp.Models
{
public class Integer
{
public int IntegerID { get; set; }
public int IntegerValue { get; set; }
public int IntegerListID { get; set; }
public virtual IntegerList IntegerList { get; set; }
}
}

integers is currently a collection of IntegerBuffer objects. Use .Select to project them to just integers:
IEnumerable<int> integers;
// ...
integers = db.IntegerBuffers
.OrderBy(i => i.IntegerBufferValue)
.Select(i => i.IntegerBufferValue);
Or:
integers =
from buffer in db.IntegerBuffers
orderby buffer.IntegerBufferValue
select buffer.IntegerBufferValue;
Then, you assign to the collection, you could do something like this:
var integerList = new IntegerList
{
Direction = direction,
Performance = watch.ElapsedMilliseconds,
Integers = integers.ToList()
};
Update:
Oops, I didn't see that Integer is a class. My answer is to create a list of Int32 objects. The basics still apply: you'll need to use select to project to whatever structure you need. Now I don't understand your data model, but perhaps you want something like this:
// Create your list first so that the list ID is saved
var integerList = new IntegerList
{
Direction = direction,
Performance = watch.ElapsedMilliseconds,
};
db.IntegerLists.Add(integerList);
// Now create your Integer records with the ID of the list
foreach (var buffer in db.IntegerBuffers.OrderBy(b => b.IntegerBufferValue))
{
db.Integers.Add(new Integer
{
IntegerValue = buffer.IntegerBufferValue,
IntegerListID = integerList.IntegerListID
});
}
If this is a one-to-many relationship, which it appears to be, then setting IntegerListID on your Integer record will implicitly add it to the Integers collection of the list.

Related

What is the right syntax for this joined EF Linq query

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()
};

Javascript object to C# object does not correctly convert double

I'm trying to send a model created using javascript (because it is created manually by the user) to an MVC controller.
The model is quite complex and one class uses the double? type for a variable. It works fine with int numbers but when I use "0.5" the value is set to null.
What is the reason why double value fail and what can I do about it?
Some code:
var serie = {};
serie.Name = $(elem).children("#name").val();
serie.UnitMeasurement = $(elem).children("#unitMeasurement").val();
serie.ThresholdRed = $(elem).children("#redThreshold").val();
serie.ThresholdYellow = $(elem).children("#yellowThreshold").val();
public class Serie
{
public string Name { get; set; }
public string UnitMeasurement { get; set; }
public double? ThresholdRed { get; set; }
public double? ThresholdYellow { get; set; }
}
You can use your class like-
public class Serie
{
public string Name { get; set; }
public string UnitMeasurement { get; set; }
public string ThresholdRed { get; set; }
public string ThresholdYellow { get; set; }
}
and then while using these varriables you can convert them like-
double? d = Convert.ToDouble(ThresholdRed);
or you can use double.TryParse like-
double d;
bool result = double.TryParse(str, out dbl); // `result` will be the status of tried Parsing (true or false)
EDITED :(
In order to avoid any confusion with culture, encode your parameters before sending like-
var serie = {};
serie.Name = escape($(elem).children("#name").val());
serie.UnitMeasurement = escape($(elem).children("#unitMeasurement").val());
serie.ThresholdRed = escape($(elem).children("#redThreshold").val());
serie.ThresholdYellow = escape($(elem).children("#yellowThreshold").val());
While using them on server, decode them first-
double? d = Convert.ToDouble(HttpUtility.HtmlDecode(ThresholdRed));

Json circular reference and 'Children could not be evaluated' on Linq Include

The following JsonResult returns:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.IntegerList_76C57D0878505062AEA67E9EB9F708830FA20FDE4F13A53543EC2E6ED84C1A2C'
and according to the debugger
'Children could not be evaluated'
for the line
var integerLists = db.IntegerLists.Include("Integers");
If I remove the include, this runs successfully. Likewise if I execute the commented code instead.
In the past, I've solved circular references by decorating my domain models with [IgnoreDataMember] but that doesn't seem to be working this time.
Controller
public JsonResult GetIntegerLists()
{
var integerLists = db.IntegerLists.Include("Integers");
//var integerLists = new List<IntegerList>();
//integerLists.Add(new IntegerList()
//{
// IntegerListID = 1,
// Direction = "Ascending",
// Performance = 467,
// Integers = { new Integer { IntegerValue = 34 }, new Integer { IntegerValue = 5654 }, new Integer { IntegerValue = 343 } }
//});
//integerLists.Add(new IntegerList()
//{
// IntegerListID = 2,
// Direction = "Ascending",
// Performance = 637,
// Integers = { new Integer { IntegerValue = 4 }, new Integer { IntegerValue = 646 }, new Integer { IntegerValue = 23 } }
//});
//integerLists.Add(new IntegerList()
//{
// IntegerListID = 3,
// Direction = "Ascending",
// Performance = 235,
// Integers = { new Integer { IntegerValue = 64378 }, new Integer { IntegerValue = 1 }, new Integer { IntegerValue = 533 } }
//});
return Json(integerLists, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult Index(IntegerList viewModel)
{
if (ModelState.IsValid)
{
db.IntegerLists.Add(viewModel);
db.SaveChanges();
}
return View();
}
Models
public class Integer
{
public int IntegerID { get; set; }
public int IntegerValue { get; set; }
public int IntegerListID { get; set; }
public virtual IntegerList IntegerList { get; set; }
}
public class IntegerList
{
public int IntegerListID { get; set; }
public string Direction { get; set; }
public long Performance { get; set; }
public virtual ICollection<Integer> Integers { get; set; }
}
You have a navigation property back to the list it belongs to. You probably don't want to use that when serializing. Use the ScriptIgnore attribute.
public class Integer
{
public int IntegerID { get; set; }
public int IntegerValue { get; set; }
public int IntegerListID { get; set; }
[ScriptIgnore]
public virtual IntegerList IntegerList { get; set; }
}

Loop Adding Records Throws Exception

Does anyone know what the proper way of adding records using loops?
I have a system that handles Inventory, Currently I need to be able to Mass Create inventory as creating 50-100 identical items with different ID's would be tedious, What I did was create a MassCreate viewmodel that would essentially take a StartID and an EndID and a base Inventory Class and in the controller loop through the difference between those two ID's and create a record
The ViewModel isn't an issue and passes the data just fine:
public class MassCreateInventoryViewModel
{
public Inventory InventoryBase { get; set; }
public int StartID { get; set; }
public int EndID { get; set; }
public IEnumerable<SelectListItem> Products { get; set; }
}
I read somewhere that the db.SaveChanges() should be outside of the loop as it should only be called once:
for (int inventoryID = viewModel.StartID; inventoryID <= viewModel.EndID; inventoryID++)
{
Inventory newInventory = new Inventory
{
InventoryID = inventoryID,
ProductID = viewModel.InventoryBase.ProductID,
DateEdited = DateTime.Now,
EditedByUserID = WebSecurity.CurrentUserId,
CustomProperties = viewModel.InventoryBase.CustomProperties
};
Database.Inventories.Add(newInventory);
if (newInventory.CustomProperties != null && newInventory.CustomProperties.Any())
{
foreach (CustomDataType dt in newInventory.CustomProperties.Select(x => x.DataType).ToList())
{
Database.Entry(dt).State = EntityState.Unchanged;
}
}
}
Database.SaveChanges();
}
But when I try looping, it stores the first record just fine then throws a Collection was modified; enumeration operation may not execute. Exception. When I include the Database.SaveChanges() after the Add method, it throws A The property 'InventoryID' is part of the object's key information and cannot be modified. error.
The InventoryID is the Key in this table but has been set so that I can input my own ID.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Inventory ID")]
public new int InventoryID { get; set; }
The Custom Property is split into two models, the first being the base class.
public class CustomProperty
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CustomPropertyID { get; set; }
public int CustomDataTypeID { get; set; }
[ForeignKey("CustomDataTypeID")]
public CustomDataType DataType { get; set; }
public string PropertyValue { get; set; }
}
and the second being the model thats mapped to the database:
[Table("CustomInventoryProperty")]
public class CustomInventoryProperty : CustomProperty
{
public int InventoryID { get; set; }
[ForeignKey("InventoryID")]
public virtual Inventory Inventory { get; set; }
}
Replace your for loop with this:
var dateEdited = DateTime.Now;
for (int inventoryID = viewModel.StartID; inventoryID <= viewModel.EndID; inventoryID++)
{
Inventory newInventory = new Inventory
{
InventoryID = inventoryID,
ProductID = viewModel.InventoryBase.ProductID,
DateEdited = dateEdited,
EditedByUserID = WebSecurity.CurrentUserId
};
if(viewModel.InventoryBase.CustomProperties != null)
{
newInventory.CustomProperties = new List<CustomProperties>();
foreach(var customProperty in viewModel.InventoryBase.CustomProperties)
{
newInventory.CustomProperties.Add(customProperty);
}
}
Database.Inventories.Add(newInventory);
Database.SaveChanges();
}

Get data from two tables (view and list) with LinQ and return into one view (code MVC-C#)

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:)

Resources