So I have the relation in the database as follows:
The idea is to add multiple product categories into the list before inserting it into the database.
I'm using ADO.NET framework, and the mapped class products contains list of product categories. So when the user fills out the form that is needed for product category I say:
Products p = new Products(... initializing);
ProductCategories p2 = new ProductCategories(...initializing);
p.ProductCategories.Add(p2);
What I don't understand is how to add more of these ProductCategories items into this list before I insert them into the database. Whenever I add new one, the old one seems to be deleted from the list, and I don't understand why? The order should be like this:
1st product category item
2nd
3rd...
(If the user stops adding them....) -> click save button -> insert all product categories from the list into product categories table...
Instead of that I just get overwritten old product category with new values that I just inserted. Can someone help me out with this??
EDIT: here is the entire code responsible for adding multiple items to the list
if (FileUpload1.PostedFile != null && FileUpload1.PostedFile.ContentLength > 0)
{
p = new Product();
// p is declared as property outside of all methods...
p.ProductName = txtProductTitle.Text;
p.Dimensions = ".";
p.PricePerUnit = float.Parse(txtProductPrice.Text);
System.Drawing.Image img = System.Drawing.Image.FromStream(FileUpload1.PostedFile.InputStream);
MemoryStream mem = new MemoryStream();
img.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
p.ProductPicture = mem.ToArray();
p.ProductPicThumb = mem.ToArray();
p.MeasurementUnitID = int.Parse(dropMeasure.SelectedValue);
p.PricePerFeet = 1.2F;
int pid = ServiceClass.InsertProduct(p);
ProductCategories p2 = new ProductCategories(...initializing);
p.ProductCategories.Add(p2);
Response.Write("<script>alert('Product successfully added!');</script>");
}
else
{
Response.Write("<script>alert('Something went wrong!');</script>");
}
Related
I am trying to do CRUD operations in c# using Linq on Products of the NWTraders Database. While Adding a new product, I am trying to display Supplier Name and Category Name instead of the Supplier ID and Category ID(which are foreign keys of the Product table).
I have tried to Add new product and it crashes soon after I press OK to save it on to the database and update my data grid. But I noticed that the new product is getting updated into the database with supplier and Category IDs as Null which is further preventing me from accessing the Product Windows form itself as it is not able to retrieve the IDs of the corresponding Supplier and Category Names that I am giving to the new product during the ADD.
cmbSupplierName.SelectedIndex seem to receiving a NULL value and this.product.Supplier.Company is throwing the Null Reference Exception. Same is the problem with category. If I handle them with the if condition, then it still throws me an exception in the below code.
private void LoadProductInformation()
{
lblProductHeader.Text = "Information about :" + this.product.ProductName;
txtProductID.Text = this.product.ProductID.ToString();
txtProductName.Text = this.product.ProductName;
// Not loading for Add Products as User has to enter the values.
if (this.Mode != ProductViewMode.Add)
{
cmbSupplierName.SelectedIndex = cmbSupplierName.FindString(this.product.Supplier.CompanyName);
cmbCategory.SelectedIndex = cmbCategory.FindString(this.product.Category.CategoryName);
txtQuantityPerUnit.Text = this.product.QuantityPerUnit;
txtUnitPrice.Text = this.product.UnitPrice.Value.ToString("C");
txtUnitsInStock.Text = this.product.UnitsInStock.Value.ToString();
txtUnitsOnOrder.Text = this.product.UnitsOnOrder.Value.ToString();
txtReorderLevel.Text = this.product.ReorderLevel.Value.ToString();
chkDiscontinued.Checked = (this.product.Discontinued == true);
}
}
public void LoadDGVProducts(IEnumerable<Product> products)
{
// If there are no products, do nothing and return from the function.
if (products == null) return;
FetchData(); //fetching all the serach parameters
this.dgvProducts.SelectionChanged -= new System.EventHandler(this.DGVProducts_SelectionChanged);
if (dgvProducts.RowCount == 0)
FormatDGVProducts();
dgvProducts.Rows.Clear();
// Go through every product in the product collection and
// add it as a row in the dgv
foreach (Product prod in products)
{
dgvProducts.Rows.Add(
prod.ProductID, // The ID will not actually be shown since it is given to a column that has the Visible property set to False.
prod.ProductName,
prod.Supplier.CompanyName,
prod.Category.CategoryName,
prod.QuantityPerUnit,
prod.UnitPrice.Value.ToString("C"),
prod.UnitsInStock,
prod.UnitsOnOrder,
prod.ReorderLevel,
prod.Discontinued
);
...........................
}
}
Due to the supplier and category IDs receiving Null values on database, it is throwing me the exceptions at the 'foreach' as it won't let product to display on data grid if even one of the values in null in that condition.
I don't know where I am supposed to connect Supplier ID to Name for it to not receive Null values on the database.
The best way to get object list has just been inserted into the
database?
I have the code to add a new object list to the database, I want to retrieve the list of objects without having to select again from the database.
I expect something like insert in the SQL Server trigger.
Here is my code snippet.
List<string> productNames = new List<string>();
foreach (var name in productNames)
{
var product = new Product {Name = name, Color = "something", Body="something body" };
DbContext.Products.Add(product);
}
DbContext.SaveChanges();
var result = ListProductsInserted; // I want to get list product
I do not want to rewrite the query to retrieve data from the database
again.
Is there a better way?
If I understaood your question properly, Use code below
List<string> productNames = new List<string>();
List<Product> holdProducts = new List<Product>();
foreach (var name in productNames)
{
var product = new Product {Name = name, Color = "something", Body="something body" };
DbContext.Products.Add(product);
holdProducts.Add(product);
}
DbContext.SaveChanges();
var result = holdProducts;
The easiest way for you would be DbEntityEntry.Reload()
you can use it like this:
yourContext.Entry(yourEntity).Reload();
My project is Windows Application c#, I am using Entity Framework 5 and .net 4.5.
I have Rooms and Beds module which you can add, edit and delete Room(s) and/or bed(s)
on my Form I have a field for RoomNo and Station, also Add and Delete button to add/delete bed(s) to datagridview, then Save button to save the Room and list of beds to DB
DB Structure
Rooms (table)
PK_Rooms
FK_Station
RoomNo
Beds (table)
PK_Beds
FK_Rooms
BedNo
FullRoomNo (concat only of Roomno and Bedno)
RoomStatus
I already implemented the "AddRoom" method which will create new Room and list of beds.
my question is how can i implement "EditRoom" method which will detect changes on the beds (added a new bed, AND/OR edited a bed number, AND/OR deleted a bed) and save it to DB?
To have a better understanding to my concern please see previous thread, which also has the AddRoom Method >
Entity Framework only saving last row (master details)
Edit:
here is my code to EditRoom method
M3dEntities m3d = new M3dEntities();
rooms rooms = new rooms();
beds beds = new beds();
string RoomNo = RoomNoTxt.Text;
int StationID = Int32.Parse(StationCmb.SelectedValue.ToString());
int _SelectedPKRoom = Int32.Parse(SelectedPKRoom);
rooms = m3d.rooms.First(x => x.PK_Rooms == _SelectedPKRoom);
{
rooms.RoomNo = RoomNo;
rooms.FK_Stations = StationID;
}
foreach (DataGridViewRow row in BedsDataGridView.Rows)
{
beds = new beds();
beds.Bedno = row.Cells[0].Value.ToString();
beds.FullRoomNo = row.Cells[1].Value.ToString();
beds.RoomStatus = "Available";
m3d.beds.AddObject(beds);
m3d.beds.DeleteObject(beds);
}
m3d.SaveChanges();
the problem with this code is only room are being updated :(
This is one Way, I hope it helps you
var room= (from g in m3d.rooms
where g.RoomNo == RoomNo
select g).FirstOrDefault(); //Take an objecto room to modify
room.FK_Stations = StationID;
foreach (DataGridViewRow row in BedsDataGridView.Rows)
{
int Bedno = row.Cells[0].Value.ToString();
var bedsChanged= (from g in m3d.beds
where g.bedno== Bedno
select g).FirstOrDefault();
bedsChanged.FullRoomNo = row.Cells[1].Value.ToString();
bedsChanged.RoomStatus = "Available";
}
m3d.SaveChanges();
My problem is that after creating an invoice, I can never get new line items to reference their corresponding sales order line item.
I have been generating invoices via SuiteTalk. When I initially create an invoice, I empty the lineItemList and add back in the items I need. I make sure the orderLine property matches the sales order line item line number. This works great.
But when I try and update the invoice with additional line items, I can never get the new items to retain their orderLine property. The orderLine property is used for the "Invoiced" column on the Sales Order.
In order to get the referencing to be correct, I need to delete the invoice and create it again with all of the line items I need.
Does anyone know if what I am trying to do is possible?
In this example, I use this CreateInvoice function to create the invoice from scratch and add it to NetSuite. Everything works as expected.
public void CreateInvoice(SalesOrder salesOrder) {
Invoice brandNewInvoice = new Invoice() {
createdFrom = new RecordRef() {
internalId = salesOrder.internalId,
},
entity = salesOrder.entity,
tranDate = endDate,
tranDateSpecified = true,
startDate = startDate,
startDateSpecified = true,
endDate = endDate,
endDateSpecified = true,
itemList = new InvoiceItemList(),
};
invoice.itemList.item = GetInvoiceItemList(salesOrder); //see the function shown further down
netSuiteService.add(brandNewInvoice);
}
In this example, the invoice is already created and so I get it from NetSuite and then replace the existing itemList with a new one. After the update, the invoice will now have NO orderLine property for any of the line items. The invoice also loses its "Created From" field because there are no line items with the orderLine property set.
public void UpdateInvoice(SalesOrder salesOrder, String invoiceInternalId) {
Invoice invoice = GetNetSuiteInvoice(invoiceInternalId);
invoice.itemList.item = GetInvoiceItemList(salesOrder); //see the function shown further down
netSuiteService.update(invoice);
}
this is the function used to create the itemList:
public InvoiceItem[] GetInvoiceItemList(SalesOrder salesOrder) {
InvoiceItem[] invoiceItemList = new InvoiceItem[salesOrder.itemList.item.Length];
for (int i = 0; i < salesOrder.itemList.item.Length; i++) {
SalesOrderItem soItem = salesOrder.itemList.item[i];
double quantity = 1;
invoiceItemList[i] = new InvoiceItem() {
item = new RecordRef() {
internalId = soItem.item.internalId,
name = soItem.item.name,
},
amount = quantity * Double.Parse(soItem.rate),
amountSpecified = true,
quantity = quantity,
quantitySpecified = true,
price = new RecordRef() {
internalId = soItem.price.internalId,
name = soItem.price.name,
},
rate = soItem.rate,
orderLine = soItem.line, //this will establish the link between the invoice and the sales order
orderLineSpecified = true,
taxRate1 = soItem.taxRate1,
taxRate1Specified = true,
};
}
return invoiceItemList;
}
Actually what you are looking for is the intialize operation. You need to use initialize in order for Netsuite to properly fill in the created from and orderline props. From the NS Help there is a C# example of creating a Cash Sale:
private void Initialize()
{
this.login(true);
InitializeRef ref1 = new InitializeRef();
ref1.type = InitializeRefType.salesOrder;
//internal id of the sales order to be converted to cash sale
ref1.internalId = "792";
ref1.typeSpecified = true;
InitializeRecord rec = new InitializeRecord();
rec.type = InitializeType.cashSale;
rec.reference = ref1;
ReadResponse read1 = _service.initialize(rec);
}
This is normal, when transforming a transaction to another transaction (e.g. SO to Inv, PO to IR). When you transform, most of the information from the source transaction will be carried over. Like what you are doing which is creating an Invoice from Sales Order(Base on your code below).
createdFrom = new RecordRef() {
internalId = salesOrder.internalId,
},
You don't need to get the line item information from the Sales Order and put it in the Invoice because it will be pre-populated once you create it form Sales Oder(unless you need to change a value of a line item column).
One behavior of a transformed record(Invoice in your case), if you remove a line item from the Invoice you will lose the link to the Sales order(orderLine) and if you remove all the line item you will totally lose the link between the two transactions (createdfrom). This is what you are experiencing. orderLine/createdFrom is a field populated by the system, it looks like you are populating it but you are not.
I am writing a parser for one of website, which have products connected to categories. I am trying to build my own database with these items.
I have decided to use Entity Framework, but I am new to this framework, so here's my problem:
During parsing i have multiple items with same category. But categories are kind of trees. I mean, category have a reference to parentCategory.
During of parsing i have a list of category inheritance f.e : category1 -> category1.1 -> category1.1.1
Each product I parse and add to database need to verify if that category exist and go through category inheritance to create non existing categories.
Code looks like this:
Category parentCategory = null;
foreach (var sCategory in categories)
{
var currentCategory = d.CategorySet.SingleOrDefault(category => category.Name == sCategory && category.Parent == parentCategory);
if (currentCategory == null)
{
currentCategory = new Category(){Name = sCategory,Parent = parentCategory};
if(parentCategory != null)
d.Entry(parentCategory).State = EntityState.Unchanged;
}
parentCategory = currentCategory;
}
But in this case, SingleOrDefault LinQ does not work because of exception:
Unable to create a constant value of type 'DataBaseModel.Category'. Only primitive types or enumeration types are supported in this context.
I know that I should compare IDs of category, but in this case it needs to saveChanges into db every time I add sth to DB.
Is there any other possibility to handle that?
I have solved this issue by creating local Dictionaries of Categories and before usage, fill this dictionaries by data from database.
_categoriesDictionary.Clear();
foreach (var category in this.Container.CategorySet)
{
Category temp = category;
string fullCategoryString = "";
while (temp != null)
{
fullCategoryString = fullCategoryString.Insert(0, temp.Name + ";");
temp = temp.Parent;
}
_categoriesDictionary.Add(fullCategoryString, category);
}
And then when analyzing the record:
Category parentCategory = null;
string fullCatString = "";
foreach (var sCategory in categories)
{
fullCatString += sCategory + ";";
Category currentCategory;
if (!_categoriesDictionary.TryGetValue(fullCatString, out currentCategory))
{
currentCategory = new Category()
{
Name = sCategory,
Parent = parentCategory
};
this.Container.CategorySet.Add(currentCategory);
_categoriesDictionary.Add(fullCatString, currentCategory);
}
parentCategory = currentCategory;
}
result.Category = parentCategory;
This has another adventage from my point of view:
Its collecting data on start, and then do not query DB every time