i have two tables orders and order detail and i have order foriegn key in order detail. and i am inserting ordertotal into order table and all other order info in order details but i am getting this error .please help me out and please tell me hw to use entity state to add values to foriegn key table.
and here is my saveorder controller function
[HttpPost]
public ActionResult SaveOrder(FormCollection fc)
{
ResturantContext context = new ResturantContext();
ShoppingCart myCart = (ShoppingCart)Session[WebUtil.CART];
User u = (User)Session[WebUtil.USER];
Order order = new Order();
order.TotalAmount = myCart.TotalAmount;
new OrderHandler().AddOrder(order);
foreach (var m in myCart.Items)
{
OrderDetails od = new OrderDetails();
od.ID = m.Id;
od.Price =m.Price;
od.Product_name = m.Name;
od.Quantity = m.Quantity;
od.Address = fc["Address"];
od.City = fc["City"];
od.DateOfOrder = DateTime.Now;
od.UserName = u.FullName;
od.Email = u.Email;
od.ContactNo = fc["ContactNo"];
od.Country = fc["Country"];
new OrderHandler().AddOrderDetails(od);
}
Session.Remove(WebUtil.CART);
return RedirectToAction("Index","Home");
}
od.Order will always be Null since you are not setting it anywhere in your code. Try at least set it like od.Order = order inside your loop before calling your OrderHandler().AddOrderDetails(od);
Related
I have an action and 2 SQL tables I know how to enter a record into 1 table but for the second table I want to get the lastly inserted ID from table 1 and insert that into the 2nd table for one of the columns. I have everything setup but my database save doesn’t work without an exception. Also Im not sure how to use scope_identity() or get the last ID and I am using EF for everything.
public ActionResult AddTimeSheet()
{
ViewBag.ProjectsSelect = new SelectList(
context.Projects.ToList(), "ProjectId", "ProjectName");
var uid = User.Identity.GetUserId();
ViewBag.CurrentId = uid;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddTimeSheet(TimeSheetProjectsModel timeSheetModel)
{
try
{
if(timeSheetModel == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//if (ModelState.IsValid)
//{
TimeSheetMaster masterModel = new TimeSheetMaster();
masterModel.FromDate = timeSheetModel.Proj1;
masterModel.ToDate = timeSheetModel.Proj1.AddDays(7);
/* NEED HRS 4 WEEK/END MONTH/NEW MONTH */
masterModel.TotalHours = timeSheetModel.ProjTotal1;
masterModel.UserId = User.Identity.GetUserId();
masterModel.DateCreated = DateTime.Now;
/* MONTH SUBMITTED */
masterModel.TimeSheetStatus = 1;
masterModel.Comment = timeSheetModel.ProjDesc1;
context.TimeSheetMaster.Add(masterModel);
var detailsModel = CreateTimeSheetDetails(masterModel, timeSheetModel);
context.TimeSheetDetails.Add(detailsModel);
context.SaveChanges();
TempData["SuccessMaster"] = "TimeSheetMaster Created Successfully";
TempData["SuccessDetails"] = "TimeSheetDetails Created Successfully";
return RedirectToAction("TimeSheetList", "TimeSheet");
//}
// TempData["Error"] = "TimeSheet Create Was Unsuccessful";
// return RedirectToAction("TimeSheetList", "TimeSheet");
}
catch (Exception ex)
{
Console.Write(ex.Message);
TempData["Error"] = "TimeSheet Create Was Unsuccessful";
return RedirectToAction("TimeSheetList", "TimeSheet");
}
}
If the two entities are associated with the same DbContext and they are directly related, (PK/FK) then the best solution is to ensure that the entities have a navigation property set up for the relation and let EF manage the keys and linking.
For instance:
TimeSheetMaster masterModel = new TimeSheetMaster();
masterModel.FromDate = timeSheetModel.Proj1;
masterModel.ToDate = timeSheetModel.Proj1.AddDays(7);
masterModel.TotalHours = timeSheetModel.ProjTotal1;
masterModel.UserId = User.Identity.GetUserId();
masterModel.DateCreated = DateTime.Now;
masterModel.TimeSheetStatus = 1;
masterModel.Comment = timeSheetModel.ProjDesc1;
var detailsModel = CreateTimeSheetDetails(masterModel, timeSheetModel);
// either here, or inside CreateTimeSheetDetails...
// if Master has a collection of Details: (1-to-Many)
masterModel.Details.Add(details);
// or if Master has a 1-to-1 relationship to details.
// masterModel.Details = detailsModel;
context.TimeSheetMaster.Add(masterModel);
context.SaveChanges();
Ideally EF should manage your relationships so that your code simply works with the related entity structure and hands off the key/relationship management to Entity Framework.
If you need IDs cross-context, or to return after performing an insert then you can access the entity's new PK directly after calling SaveChanges:
context.TimeSheetMaster.Add(masterModel);
context.SaveChanges();
var newId = masterModel.TimeSheetMasterId; // Populated automatically after SaveChanges.
I'm trying to copy ProductStatisticsTemp table data to ProductStatistics table,
var str = from a in db.ProductStatisticsTemp select a;
ProductStatistics ls = new ProductStatistics();
foreach (var val in str.ToList())
{
ls.Product_ID = val.Product_ID;
ls.ProductNameEn = val.ProductNameEn;
ls.ProductNameAr = val.ProductNameAr;
db.ProductStatistics.Add(ls);
db.SaveChanges();
}
first record can insert but once its try to insert 2nd one getting following error
The property 'Product_ID' is part of the object's key information and
cannot be modified.
It's because you have one instance of an object and try to add already added object twice.
You need to create new object of ProductStatistics in the loop.
Also you can save changes just once after the loop to improve performance by trigger DB communication just once:
var str = from a in db.ProductStatisticsTemp select a;
foreach (var val in str.ToList())
{
ProductStatistics ls = new ProductStatistics
{
Product_ID = val.Product_ID,
ProductNameEn = val.ProductNameEn,
ProductNameAr = val.ProductNameAr
};
db.ProductStatistics.Add(ls);
}
db.SaveChanges();
Here is a slightly different method.
var products = db.ProductStatisticsTemp.Select(t => new ProductStatistics
{
Product_ID = t.Product_ID,
ProductNameEn = t.ProductNameEn,
ProductNameAr = t.ProductNameAr
}).ToList()
db.ProductStatistics.AddRange(products);
db.SaveChanges();
IMHO Inspired from #Vadim Martynov
If the Product_ID is your primary key, and your set to increment
the key from database . Do not do this Product_ID = val.Product_ID.
The key should be generated from the database. You will get the id
after save changes is invoked.
try
{
var str = from a in db.ProductStatisticsTemp select a;
//This will improve some performance
db.Configuration.AutoDetectChangesEnabled = false;
foreach (var val in str.ToList())
{
ProductStatistics ls = new ProductStatistics
{
Product_ID = val.Product_ID,
ProductNameEn = val.ProductNameEn,
ProductNameAr = val.ProductNameAr
};
//use AddRange or Add based on your EF Version.
db.ProductStatistics.Add(ls);
}
db.SaveChanges();
}
finally
{
db.Configuration.AutoDetectChangesEnabled = true;
}
If you are using AddRange you could omit db.Configuration.AutoDetectChangesEnabled = false
For more info about DetectChanges available here
AddRange() method only support from EF6 see documentation
db.ProductStatistics.AddRange(products);
What AddRange will do for you is
if AutoDetectChangesEnabled is set to true (which is the default), then DetectChanges will be called once before adding any entities and will not be called again.
This means that in some situations AddRange may perform significantly
better than calling Add multiple times would do.
Note that entities that are already in the context in some other state will have their state set to Added. AddRange is a no-op for entities that are already in the context in the Added state.
Can anyone tell where I make a mistake ? :( I want to insert a row using this. It's just not working. I also tried to use "context.SaveChanges();" but nothing changed. No insert at all, and no exception.
public List<string> Add_Address(string address, int selected_item)
{
List<string> list = new List<string>();
using(var context = new RSS_Reader_Database())
{
Address Address = new Address();
Category_Address Category_Address = new Category_Address();
Address.URL = address.ToString();
int max_id = Convert.ToInt32(context.Addresses.OrderByDescending(t => t.ID_Address).FirstOrDefault());
Category_Address.ID_Address = max_id;
Category_Address.ID_Category = selected_item+1;
var select_query = from t in context.Addresses select t.URL;
foreach (var element in select_query)
{
list.Add(element);
}
}
return list;
}
Edit: Following all Your advices, I made something that works. Looking at this code above, I have no idea what I was trying to do yesterday. Thanks a lot.
public List<string> Add_Address(string address, int selected_item)
{
List<string> list = new List<string>();
using(var context = new RSS_Reader_Database())
{
Address Address = new Address() { URL = address };
context.Addresses.Add(Address);
context.SaveChanges();
int max_id = context.Addresses.Max(u => u.ID_Address);
Category_Address Category_Address = new Category_Address() { ID_Address = max_id, ID_Category = selected_item + 1 };
context.Categories_Addresses.Add(Category_Address);
context.SaveChanges();
var query = from t in context.Addresses
select t.URL;
var data = query.ToList();
foreach (var element in data)
{
list.Add(element);
}
}
return list;
}
Saving with Entity Framework generally works like this. Using your above code as a starting point.
using(var context = new RSS_Reader_Database())
{
Address address = new Address();
// Set address properties
context.Addresses.Add(address);
context.SaveChanges();
}
You need to add the object to the DbSet<T> where T is the type of the entity that is defined on the DbContext. You then need to call SaveChanges() on the context.
I would suggest reading this. It is an easy to follow introduction to Entity Framework.
Not sure exactly what you are trying to do.
But if you are expecting to insert the data by the list.Add(element); command it won't work.
If you are planning to insert data into the same DB, you need to use one property from the context to represent the List collection add a new element on this property.
Something like:
context.Lists.Add(element);
if you want retrieve data, you should not call SaveChanges() !,
try get all values from one query like this:
List<string> select_query = (from t in context.Addresses select t.URL).ToList();
I have an issue that I am trying to resolve where I have a relationship between two tables. As soon as I save a record to the 1st Table I then want to read that same record back so I can get the primary key and assign it to my next table.
Code I have written is below
public IEnumerable<CombinedPayCode> ImportCombinedPayCodes()
{
var xmlFile = Path.Combine(_xmlPath, "WSACombinedPayCodeRule.xml");
var stream = new FileStream(xmlFile, FileMode.Open, FileAccess.Read);
var xdoc = XDocument.Load(stream);
var combinedPayCodeCollection = xdoc.Descendants("WSACombinedPayCodeRule");
var Collection = new List<CombinedPayCode>();
foreach (var element in combinedPayCodeCollection)
{
var combinedPayCode = new CombinedPayCode
{
Name = (string)element.Attribute("Name"),
AmountType = (string)element.Attribute("AmountType"),
VisibleInReport = (bool)element.Attribute("VisibleInReport"),
MoneyCategory = (bool)element.Attribute("MoneyCategory"),
VisibleToUser = (bool)element.Attribute("VisibleToUser"),
CustomerId = 11,
};
_db.CombinedPayCodes.Add(combinedPayCode);
// I want to obtain the Primary Key of the above record once saved to database
var payCodeNodes = element.Descendants("SimpleValue");
foreach (var selectedPayCode in payCodeNodes)
{
var combinedPayCodeList = new CombinedPayCodeList
{
PayCodeId = selectedPayCode.FirstAttribute.Value,
// I want to replace the next line of code to assign the
// foreign key as per the primary key of the record above
CombinedPayCodeId = 1,
};
_db.CombinedPayCodeLists.Add(combinedPayCodeList);
}
_db.SaveChanges();
Collection.Add(combinedPayCode);
}
return Collection;
}
Is the primary key of CombinedPayCode an identity column? If so, just reference combinedPayCode.ThePrimaryKeyColumn in your code.
If CombinedPayCodeList is a collection of something that hangs off CombinedPayCode you can save yourself some effort and just build the object graph and add the parent object then SubmitChanges(). EF will take care of transferring the primary key into the child entity and wrap everything in a nice neat transaction for you.
UPDATE: Something like this. I may have some of your object/property names wrong.
foreach( var element in combinedPayCodeCollection )
{
// Create the CombinedPayCode object
var combinedPayCode = new CombinedPayCode
{
Name = (string)element.Attribute("Name"),
AmountType = (string)element.Attribute("AmountType"),
VisibleInReport = (bool)element.Attribute("VisibleInReport"),
MoneyCategory = (bool)element.Attribute("MoneyCategory"),
VisibleToUser = (bool)element.Attribute("VisibleToUser"),
CustomerId = 11,
};
var payCodeNodes = element.Descendants("SimpleValue");
foreach( var selectedPayCode in payCodeNodes )
{
var combinedPayCodeList = new CombinedPayCodeList
{
PayCodeId = selectedPayCode.FirstAttribute.Value,
};
// Add each PayCodeNode to the CombinedPayCode
combinedPayCode.CombinedPayCodeLists.Add( combinedPayCodeList );
}
// Add the CombinedPayCode (which includes all the PayCodeNodes) to
// the object context and save the whole shebang.
_db.CombinedPayCodes.Add(combinedPayCode);
_db.SaveChanges();
I'm guess that you are using Entity Framework based off the syntax.
You can do this:
_db.CombinedPayCodes.Add(combinedPayCode);
_db.SaveChanges();
Then combinedPayCode.Id should have it's primary key. This not the best way to do it if you need that ID as a Foreign key on another table. Then you would do:
combinedPayCode.CombinedPayCodeLists.Add(combinedPayCodeList);
_db.CombinedPayCodes.Add(combinedPayCode);
_db.SaveChanges();
In this case you only have to save one time, and it wraps all the db changes in a transaction. If one fails, they all fail.
Hope this helps!
I'm having trouble performing an update in the Entity Framework. I don't really understand the behaviour I am seeing.
I am using the AdventureWorks database.
The starting value for the StateProvince is Micronesia. If I change it to Maryland, the update is successful. However, if I then try to change it back to Micronesia, I get the following error:
"Cannot insert duplicate key row in object 'Sales.SalesTerritory' with
unique index 'AK_SalesTerritory_Name'.\r\nThe statement has been
terminated."
The DAL method in question is:
public static void UpdateCustomer(CustomerDetails customerDetails)
{
AWEntities context = Common.GetContext();
var customerQuery = from c in context.Individuals
.Include("Contact")
.Include("Customer.CustomerAddresses.Address.StateProvince.SalesTerritory")
//.Include("Customer.SalesTerritory.StateProvinces")
.Where(id => id.CustomerID == customerDetails.CustomerId)
select c;
var individual = customerQuery.ToList().ElementAt(0);
Contact contact = individual.Contact;
contact.LastName = customerDetails.LastName;
contact.MiddleName = customerDetails.MiddleName;
contact.FirstName = customerDetails.FirstName;
contact.EmailAddress = customerDetails.EmailAddress;
contact.Phone = customerDetails.Phone;
contact.Title = customerDetails.Title;
AWModel.Customer customer = individual.Customer;
customer.CustomerID = customerDetails.CustomerId;
customer.SalesTerritory.Name = customerDetails.SalesTerritory;
Address address = individual.Customer.CustomerAddresses.ElementAt(0).Address;
address.AddressLine1 = customerDetails.AddressLine1;
address.AddressLine2 = customerDetails.AddressLine2;
address.City = customerDetails.City;
address.PostalCode = customerDetails.PostalCode;
address.StateProvinceID = customerDetails.SalesProvinceId;
context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
}
Can anyone identify the correct way to do what I am attempting.
This is occurring when you update the SalesTerritory.Name property:
customer.SalesTerritory.Name = customerDetails.SalesTerritory;
The effect is to change the SalesTerritory entity, rather than the customer entity. I believe you want something more like:
customer.SalesTerritoryID = customerDetails.SalesTerritoryID;