Query not updating database - c#

Morning,
I have an issue with some of my code...
Basically i am trying to update or insert into the database. the first if statement if for when adding a new product. the else should then update any existing products.
However when i run it, it is not updating the existing products in the database. It is however setting the items ready to be updated. Any ideas?
Many thanks...
using (aboDataDataContext dc = new aboDataDataContext())
{
foreach (abcProduct p in abcProducts)
{
var match = (from t in dc.abcProducts
where t.sku == p.productcode
select t).FirstOrDefault();
if (match == null)
{
// Watch out here; there is some type conversion required for certain fields!
abcProduct prod = new abcProduct();
prod.sku = p.productcode;
prod.categoryId = dc.Categories.Single(c => c.Name == p.category).Id;
prod.title = p.name;
prod.brand = p.manufacturer;
prod.description = p.description;
prod.abcPrice = p.price;
prod.size = decimal.TryParse(p.size.Replace("cl", ""), out size) == true ? (int?)size : null;
prod.country = p.country;
prod.region = p.region;
prod.vintage = int.TryParse(p.vintage, out vintage) == true ? (int?)vintage : null;
prod.weight = Convert.ToDecimal("1.50");
prod.strength = p.strength;
prod.bottler = p.bottler;
prod.age = int.TryParse(p.age, out age) == true ? (int?)age : null;
prod.caskType = p.casktype;
prod.series = p.series;
prod.flavour = p.flavour;
if (p.freestock <= 0) { prod.stock = 0; } //check to see if stock is 0
else { prod.stock = p.freestock; }
prod.abcUpdated = false;
prod.stockUpdated = false;
prod.priceUpdated = false;
prod.pricePublished = false;
prod.stockPublished = false;
prod.imgPublished = false;
prod.prodPublished = false;
prod.lastUpdated = DateTime.Now;
// Add the new object to the abcProducts table (only in memory here)
dc.abcProducts.InsertOnSubmit(prod);
}
else
{
// update row
match.abcUpdated = true;
//Set if an item has been updated or not.
if (match.stock == p.freestock) { match.stockUpdated = false; }
else { match.stockUpdated = true; }
if (match.abcPrice == p.price) { match.priceUpdated = false; }
else { match.priceUpdated = true;}
match.sku = p.productcode;
match.categoryId = dc.Categories.Single(c => c.Name == p.category).Id;
match.title = p.name;
match.brand = p.manufacturer;
match.description = p.description;
match.stock = p.freestock;
match.abcPrice = p.price;
match.size = decimal.TryParse(p.size.Replace("cl", ""), out size) == true ? (int?)size : null;
match.weight = Convert.ToDecimal("1.50");
match.country = p.country;
match.region = p.region;
match.vintage = int.TryParse(p.vintage, out vintage) == true ? (int?)vintage : null;
match.strength = p.strength;
match.bottler = p.bottler;
match.age = int.TryParse(p.age, out age) == true ? (int?)age : null;
match.caskType = p.casktype;
match.series = p.series;
match.flavour = p.flavour;
if (p.freestock <= 0) { match.stock = 0; } //check to see if stock is 0
else { match.stock = p.freestock; }
match.abcUpdated = true;
match.pricePublished = false;
match.stockPublished = false;
match.imgPublished = false;
match.prodPublished = false;
match.lastUpdated = DateTime.Now;
}
}
// Finally, request Linq to perform the database updates.
dc.SubmitChanges();
}
return null;
}

The context is loosing track of the object when setting match.
At the bottom of the else statement insert
dc.abcProducts.Attach(match);

There is problem in your code, you are iterating through the product table and getting the values in the match variable. In the part of the if statement where match is not null, you are setting the object to the new values, but you are not calling the dc.SubmitChanges();, that object match is not getting stored any where in your code, and in the next iteration in the loop, it is being assigned the new values.
You need to call dc.SubmitChanges(); after update the match values.
foreach (abcProduct p in abcProducts)
{
var match = (from t in dc.abcProducts
where t.sku == p.productcode
select t).FirstOrDefault();
if (match == null)
{
//insertion code commented out
dc.abcProducts.InsertOnSubmit(prod);
}
else
{
///.... setting up all fields.
match.stockPublished = false;
match.imgPublished = false;
match.prodPublished = false;
match.lastUpdated = DateTime.Now;
dc.SubmitChanges(); //Call this otherwise you will
//loose the match values in the next iteration
}
}

Related

How to trigger TreeView NodeMouseClick and CursorChanged events with a method. I am getting error on parameter `e` due to incompatible parameters

I managed to create a TreeView method for NodeMouseClick and CursorChanged events.
private void Node_Selection_Action(object sender, TreeNodeMouseClickEventArgs e)
{
// my action code here...
}
private void TvwPanel_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
Node_Selection_Action(sender, e);
}
However, I am getting an error on e parameter when I applied the method to the CursorChanged:
private void TvwPanel_CursorChanged(object sender, EventArgs e)
{
Node_Selection_Action(sender, e); //error on `e` here
}
I supposed this is due to the parameter EventArgs that is not compatible with my method parameter TreeNodeMouseClickEventArgs.
Is there any workaround that I could use to trigger the CursorChanged event with my method?
UPDATE 1:
As requested, here's the bunch of code for the Node_Selection_Action method:
private void Node_Selection_Action(object sender, TreeNodeMouseClickEventArgs e)
{
TvwPanel.SelectedNode = e.Node;
if (Convert.ToString(e.Node.Tag) == "a") //profile Convert.ToInt16()
{
TsmNewPr.Enabled = false;
TsmNewDb.Visible = false;
TsmNewCo.Visible = false;
TsmNewTk.Visible = false;
TsmNewTkCred.Visible = false;
TsmNewLg.Visible = false;
TsmEditPr.Enabled = true;
TsmEditDb.Visible = false;
TsmEditCo.Visible = false;
TsmEditTk.Visible = false;
TsmEditTkCred.Visible = false;
TsmEditLg.Visible = false;
TsmDeletePr.Enabled = true;
TsmDeleteDb.Visible = false;
TsmDeleteCo.Visible = false;
TsmDeleteTk.Visible = false;
TsmDeleteTkCred.Visible = false;
TsmDeleteLg.Visible = false;
TsmRunTk.Enabled = false;
TsmRefreshLg.Enabled = false;
TsmHelpAll.Enabled = true;
}
else if (Convert.ToString(e.Node.Tag) == "b") //database
{
TsmNewPr.Visible = false;
TsmNewDb.Enabled = true;
// arbitrary control if database already exists. If exists disable, otherwise enable.
#region TsmNewDb.Enabled (true/false)
selNodeParentName = TvwPanel.SelectedNode.Parent.Text;
selNodeName = TvwPanel.SelectedNode.Text;
Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml();
XElement xmlComplete = XElement.Load(xcf.xmlProfileComplete);
IEnumerable<XElement> profile =
from ep in xmlComplete.Elements("node")
where (string)ep.Attribute("text") == selNodeParentName
select ep;
foreach (XElement epi in profile)
{
IEnumerable<XElement> profNode =
from en in epi.Elements("node")
where (string)en.Attribute("text") == selNodeName
select en;
foreach (XElement enc in profNode)
{
// get the attribute texts
var childrenTexts = enc.Elements("node").Attributes("text");
foreach (var childText in childrenTexts)
{
if (childText.Value != "Type" || childText.Value != "Name" || childText.Value != "Connection")
{
// enable TsmNewDb ContextMenu button if does not exists yet
TsmNewDb.Enabled = false;
}
}
// initialize the attribute tags to null
string TypeTag = null;
string NameTag = null;
string ConnTag = null;
// get the attribute tags
var childrenTags = enc.Elements("node").Attributes("tag");
int count = 0;
// get db details for showing on the right panel of the main form specified below
foreach (var childTag in childrenTags)
{
if (count == 0)
{
TypeTag = childTag.Value;
}
else if (count == 1)
{
NameTag = childTag.Value;
}
else if (count == 2)
{
ConnTag = childTag.Value;
}
count++;
}
// check if database exists
if (db.Databases_Exists(ConnTag) == true)
{
// convert the password to "*" for display purposes
string s = ConnTag;
int start = s.LastIndexOf("pwd=") + "pwd=".Length;
int end = s.IndexOf(";", start);
string result = s.Substring(start, end - start);
s = s.Replace(result, "********");
ConnTag = s;
// transfer data FrmDatabase form to main form tabcontrol panel
LblDbTypeDef.Text = TypeTag;
LblDbNameDef.Text = NameTag;
LblDbConnDef.Text = ConnTag;
// make the main tabcontrol panel visible to true
TbcMain.SelectedIndex = 0;
TbcMain.Visible = true;
}
else
{
// make the main tabcontrol panel visible to false
TbcMain.SelectedIndex = 0;
TbcMain.Visible = false;
}
}
}
#endregion
TsmNewCo.Visible = false;
TsmNewTk.Visible = false;
TsmNewTkCred.Visible = false;
TsmNewLg.Visible = false;
TsmEditPr.Visible = false;
TsmEditDb.Enabled = true;
TsmEditCo.Visible = false;
TsmEditTk.Visible = false;
TsmEditTkCred.Visible = false;
TsmEditLg.Visible = false;
TsmDeletePr.Visible = false;
TsmDeleteDb.Enabled = true;
TsmDeleteCo.Visible = false;
TsmDeleteTk.Visible = false;
TsmDeleteTkCred.Visible = false;
TsmDeleteLg.Visible = false;
TsmRunTk.Enabled = false;
TsmRefreshLg.Enabled = false;
TsmHelpAll.Enabled = true;
}
else if (Convert.ToString(e.Node.Tag) == "c") //company file
{
TsmNewPr.Visible = false;
TsmNewDb.Visible = false;
TsmNewCo.Enabled = true;
// arbitrary control if company file already exists. If exists, disable, otherwise enable.
#region TsmNewCo.Enabled (true/false)
selNodeParentName = TvwPanel.SelectedNode.Parent.Text;
selNodeName = TvwPanel.SelectedNode.Text;
Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml();
XElement xmlComplete = XElement.Load(xcf.xmlProfileComplete);
IEnumerable<XElement> profile =
from ep in xmlComplete.Elements("node")
where (string)ep.Attribute("text") == selNodeParentName
select ep;
foreach (XElement epi in profile)
{
IEnumerable<XElement> profNode =
from en in epi.Elements("node")
where (string)en.Attribute("text") == selNodeName
select en;
foreach (XElement enc in profNode)
{
// get the attribute texts
var childrenTexts = enc.Elements("node").Attributes("text");
foreach (var childText in childrenTexts)
{
if (childText.Value != "Company Name" || childText.Value != "File Path")
{
// enable TsmNewCo ContextMenu button if does not exists yet
TsmNewCo.Enabled = false;
}
}
// initialize the attribute tags to null
string CoFileTag = null;
string FilePathTag = null;
// get the attribute tags
var childrenTags = enc.Elements("node").Attributes("tag");
int count = 0;
// get db details for showing on the right panel of the main form specified below
foreach (var childTag in childrenTags)
{
if (count == 0)
{
CoFileTag = childTag.Value;
}
else if (count == 1)
{
FilePathTag = childTag.Value;
}
count++;
}
// show db details on the right panel of the main form
if (CoFileTag != null || FilePathTag != null)
{
TbcMain.SelectedIndex = 1;
TbcMain.Visible = true;
LblCompanyFileDef.Text = CoFileTag;
LblFilePathDef.Text = FilePathTag;
}
else
{
TbcMain.SelectedIndex = 1;
TbcMain.Visible = false;
}
}
}
#endregion
TsmNewTk.Visible = false;
TsmNewTkCred.Visible = false;
TsmNewLg.Visible = false;
TsmEditPr.Visible = false;
TsmEditDb.Visible = false;
TsmEditCo.Enabled = true;
TsmEditTk.Visible = false;
TsmEditTkCred.Visible = false;
TsmEditLg.Visible = false;
TsmDeletePr.Visible = false;
TsmDeleteDb.Visible = false;
TsmDeleteCo.Enabled = true;
TsmDeleteTk.Visible = false;
TsmDeleteTkCred.Visible = false;
TsmDeleteLg.Visible = false;
TsmRunTk.Enabled = false;
TsmRefreshLg.Enabled = false;
TsmHelpAll.Enabled = true;
}
else if (Convert.ToString(e.Node.Tag) == "d") //tasks
{
TsmNewPr.Visible = false;
TsmNewDb.Visible = false;
TsmNewCo.Visible = false;
TsmNewTk.Enabled = true;
#region Enable/Disable "New" if database and company file are not saved yet
selNodeParentName = TvwPanel.SelectedNode.Parent.Text;
selNodeDbSiblingName = TvwPanel.SelectedNode.PrevNode.PrevNode.Text;
selNodeCoSiblingName = TvwPanel.SelectedNode.PrevNode.Text;
Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml();
XElement xmlComplete = XElement.Load(xcf.xmlProfileComplete);
IEnumerable<XElement> profile =
from ep in xmlComplete.Elements("node")
where (string)ep.Attribute("text") == selNodeParentName
select ep;
// inquire if database has child or db already, if not this node is disabled
foreach (XElement epi in profile)
{
IEnumerable<XElement> profNode =
from en in epi.Elements("node")
where (string)en.Attribute("text") == selNodeDbSiblingName
select en;
if (profNode.Descendants().Count() == 0)
{
TsmNewTk.Enabled = false;
}
}
// inquire if company file has child or has file already, if not this node is disabled
foreach (XElement epi in profile)
{
IEnumerable<XElement> profNode =
from en in epi.Elements("node")
where (string)en.Attribute("text") == selNodeCoSiblingName
select en;
if (profNode.Descendants().Count() == 0)
{
TsmNewTk.Enabled = false;
}
else
{
foreach (XElement enc in profNode)
{
// get the attribute tags
var childrenTags = enc.Elements("node").Attributes("tag");
int count = 0;
// get company details for showing on the right panel of the main form specified below for task creation
foreach (var childTag in childrenTags)
{
if (count == 1)
{
qbFilePath = childTag.Value;
}
count++;
}
}
}
}
#endregion
TsmNewTkCred.Visible = false;
TsmNewLg.Visible = false;
TsmEditPr.Visible = false;
TsmEditDb.Visible = false;
TsmEditCo.Visible = false;
TsmEditTk.Enabled = false;
TsmEditTkCred.Visible = false;
TsmEditLg.Visible = false;
TsmDeletePr.Visible = false;
TsmDeleteDb.Visible = false;
TsmDeleteCo.Visible = false;
TsmDeleteTk.Enabled = false;
TsmDeleteTkCred.Visible = false;
TsmDeleteLg.Visible = false;
TsmRunTk.Enabled = false;
TsmRefreshLg.Enabled = false;
TsmHelpAll.Enabled = true;
// arbitrary control for showing up tasks summary
#region Extract data from Xml and show in the main form tabcontrol
selNodeParentName = TvwPanel.SelectedNode.Parent.Text;
selNodeName = TvwPanel.SelectedNode.Text;
if (Xml_Extract_Data_TaskSum(selNodeParentName, selNodeName) == true)
{
TbcMain.SelectedIndex = 2;
TbcMain.Visible = true;
}
else
{
TbcMain.SelectedIndex = 2;
TbcMain.Visible = false;
}
#endregion
}
else // for the task credentials
{
TsmNewPr.Visible = false;
TsmNewDb.Visible = false;
TsmNewCo.Visible = false;
TsmNewTk.Visible = false;
TsmNewTkCred.Enabled = false;
TsmNewLg.Visible = false;
TsmEditPr.Visible = false;
TsmEditDb.Visible = false;
TsmEditCo.Visible = false;
TsmEditTk.Visible = false;
TsmEditTkCred.Enabled = true;
TsmEditLg.Visible = false;
TsmDeletePr.Visible = false;
TsmDeleteDb.Visible = false;
TsmDeleteCo.Visible = false;
TsmDeleteTk.Visible = false;
TsmDeleteTkCred.Enabled = true;
TsmDeleteLg.Visible = false;
TsmRunTk.Enabled = true;
TsmRefreshLg.Enabled = false;
TsmHelpAll.Enabled = true;
// arbitrary control for showing up tasks details
#region Extract data from Xml and show in the main form tabcontrol
selNodeGrandParentName = TvwPanel.SelectedNode.Parent.Parent.Text;
selNodeDbSiblingName = TvwPanel.SelectedNode.Parent.PrevNode.PrevNode.Text;
selNodeCoSiblingName = TvwPanel.SelectedNode.Parent.PrevNode.Text;
selNodeParentName = TvwPanel.SelectedNode.Parent.Text;
selNodeName = TvwPanel.SelectedNode.Text;
Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml();
XElement xmlComplete = XElement.Load(xcf.xmlProfileComplete);
IEnumerable<XElement> profileTask =
from ep in xmlComplete.Elements("node")
where (string)ep.Attribute("text") == selNodeGrandParentName
select ep;
foreach (XElement ep in profileTask)
{
IEnumerable<XElement> profNodeTask =
from en in ep.Elements("node")
where (string)en.Attribute("text") == selNodeParentName
select en;
foreach (XElement ept in profNodeTask)
{
IEnumerable<XElement> profNodeTaskCred =
from en in ept.Elements("node")
where (string)en.Attribute("text") == selNodeName
select en;
foreach (XElement eptc in profNodeTaskCred)
{
// initialize the attribute tags to null
string ActionTag = null;
string TablesTag = null;
string FiltersTag = null;
string ScheduleTag = null;
// get the attribute tags
var childrenTags = eptc.Elements("node").Attributes("tag");
int count = 0;
// get db details for showing on the right panel of the main form specified below
foreach (var childTag in childrenTags)
{
if (count == 0)
{
ActionTag = childTag.Value;
}
else if (count == 1)
{
TablesTag = childTag.Value;
}
else if (count == 2)
{
FiltersTag = childTag.Value;
}
else if (count == 3)
{
ScheduleTag = childTag.Value;
}
count++;
}
// show db details on the right panel of the main form
if (ActionTag != null || FiltersTag != null || ScheduleTag != null)
{
LblActionDef.Text = ActionTag;
// TablesTag
string[] TablesTagArray = TablesTag.Split(','); //(new char[] { ',', ' ' });
LvwTables.Items.Clear();
foreach (string tt in TablesTagArray)
{
string table = tt.TrimStart();
ListViewItem lvi = new ListViewItem(table);
LvwTables.Items.Add(lvi);
}
// FiltersTag
// filter period
string filterPeriod;
int Pos1 = FiltersTag.IndexOf("Transactions: ") + "Transactions: ".Length;
int Pos2 = FiltersTag.IndexOf(" | Migration");
filterPeriod = FiltersTag.Substring(Pos1, Pos2 - Pos1);
LblFtrPeriodDef.Text = filterPeriod;
// migration type
string migrationType;
int Pos3 = FiltersTag.IndexOf("Type: ") + "Type: ".Length;
int Pos4 = FiltersTag.IndexOf(" | No");
migrationType = FiltersTag.Substring(Pos3, Pos4 - Pos3);
LblFtrMigTypeDef.Text = migrationType;
// no of record per query
string numberRecords;
int Pos5 = FiltersTag.IndexOf("Query: ") + "Query: ".Length;
numberRecords = FiltersTag.Substring(Pos5);
LblFtrRpqDef.Text = numberRecords;
// filter head
if (filterPeriod == "All" && migrationType == "Overwrite" && numberRecords == "0")
{
LblFiltersDef.Text = "Default";
}
else
{
LblFiltersDef.Text = "Custom";
}
LblSchedDef.Text = ScheduleTag;
TbcMain.SelectedIndex = 3;
TbcMain.Visible = true;
}
else
{
TbcMain.SelectedIndex = 3;
TbcMain.Visible = false;
}
}
}
}
// capture the db credentials for task running
Capture_DB_Credentials_for_NodeMouseClick_And_Task_Saving(selNodeGrandParentName, selNodeDbSiblingName, selNodeCoSiblingName);
#endregion
}
if (e.Button == MouseButtons.Right)
{
Point ClickPoint = new Point(e.X, e.Y);
TreeNode ClickNode = TvwPanel.GetNodeAt(ClickPoint);
if (ClickNode == null) return;
// Convert from Tree coordinates to Screen coordinates
Point ScreenPoint = TvwPanel.PointToScreen(ClickPoint);
// Convert from Screen coordinates to Form coordinates
Point FormPoint = this.PointToClient(ScreenPoint);
CmsPanel.Show(this, FormPoint);
}
}
In the Node_Selection_Action method, the last if statement block:
if (e.Button == MouseButtons.Right)
{
Point ClickPoint = new Point(e.X, e.Y);
TreeNode ClickNode = TvwPanel.GetNodeAt(ClickPoint);
if (ClickNode == null) return;
// Convert from Tree coordinates to Screen coordinates
Point ScreenPoint = TvwPanel.PointToScreen(ClickPoint);
// Convert from Screen coordinates to Form coordinates
Point FormPoint = this.PointToClient(ScreenPoint);
CmsPanel.Show(this, FormPoint);
}
is the only block of code that needs the TreeNodeMouseClickEventArgs properties. If you really need to pass this type of argument to the method then create one:
// Still no idea what is the relation, however...
private void TvwPanel_CursorChanged(object sender, EventArgs e)
{
var s = sender as TreeView;
var p = s.PointToClient(Cursor.Position);
var ht = s.HitTest(p);
if (ht.Node != null)
{
var args = new TreeNodeMouseClickEventArgs(ht.Node, MouseButtons, 1, p.X, p.Y);
Node_Selection_Action(s, args);
}
}
Unless I'm missing an access to the sender param in your code, you can omit it to simplify the method signature:
private void Node_Selection_Action(TreeNodeMouseClickEventArgs e) { }
Also, you can determine which mouse button is pressed anywhere in your code through the Control.MouseButtons property. The Control.MousePosition property gets the cursor's position in screen coordinates. So, maybe these two properties are all what you need.
Maybe the mentioned above last if block is in the wrong method and moving it into a new method or elsewhere in the context could be better.
Hope that helps.

db.SaveChanges in ForEach causes 'New transaction is not allowed because there are other threads running in the session'

I have an excel file with about 21000 rows . I imported it into a temp Table in my database.
Now I want to do some conversions on my data and then put them into my main table.
When I do SaveChanges() inside a foreach I got the following error:
Microsoft.Data.SqlClient.SqlException: 'New transaction is not allowed because there are other threads running in the session
When I use it after the foreach no error occurs and the table has just 4 records inserted instead of all 21000 records that I expected.
public ActionResult FeedTempdataToMainDB()
{
var L = new Leave();
// var leaves = new List<Leave>();
foreach (var item in db.TempLeaves)
{
L.Pcode = Int32.Parse(item.Cod);
var z = int.Parse(item.LT) - 1;
if (z == 0) L.LT = Leave.LeaveType.Saati;
else L.LT = Leave.LeaveType.Roozane;
var o = int.Parse(item.DLT) - 1;
if (o == 0) L.DLT = Leave.DLType.Estehghaghi;
if (o == 1) L.DLT = Leave.DLType.Estelaji;
else L.DLT = Leave.DLType.Bihoghoogh;
L.LeaveDayStart = item.LeaveDayStart.Old6digToMiladi();
L.LeaveDayEnd = item.LeaveDayEnd.Old6digToMiladi();
L.LeaveTimeStart = StringToHour(item.LeaveTimeStart);
L.LeaveTimeEnd = StringToHour(item.LeaveTimeEnd);
L.LeaveDays = int.Parse(item.LeaveDays);
L.LeaveMinuts = SaatiLengh(item.LeaveMinuts);
L.RegDate = StringToHour(item.RegTime);
L.RegDate = item.RegDate.Old6digToMiladi().Date;
L.RegistrarCode = Int32.Parse(item.RegistrarCode);
L.HijriYear = L.LeaveDayStart.GetHijriYear();
var t = IsOk(item.RegTime);
if (L.DLT == 0 && t == false || L.LT == 0)
{
L.Calculate = false;
L.IsActive = false;
}
else { L.Calculate = true; L.IsActive = true; }
db.Leaves.Add(L);
db.SaveChangesAsync();
}
//db.SaveChanges();
return RedirectToAction("index");
You have a bug in your code. You declared and created L outside of the loop. Each time you add the same L , only with different data. In the end you have list of the same data that was created during the last foreach loop cicle.
try this:
foreach (var item in db.TempLeaves)
{
var z = int.Parse(item.LT) - 1;
var L = new Leave{
Pcode = Int32.Parse(item.Cod),
LeaveTimeStart = StringToHour(item.LeaveTimeStart),
LeaveTimeEnd = StringToHour(item.LeaveTimeEnd),
LeaveDays = int.Parse(item.LeaveDays),
LT = z == 0? Leave.LeaveType.Saati : Leave.LeaveType.Roozane
};
db.Leaves.Add(L);
}
or this
var leaves= new List<Leave>();
foreach (var item in db.TempLeaves)
{
var z = int.Parse(item.LT) - 1;
var L = new Leave{
Pcode = Int32.Parse(item.Cod),
LeaveTimeStart = StringToHour(item.LeaveTimeStart),
LeaveTimeEnd = StringToHour(item.LeaveTimeEnd),
LeaveDays = int.Parse(item.LeaveDays),
LT = z == 0? Leave.LeaveType.Saati : Leave.LeaveType.Roozane
};
leaves.Add(L);
}
if(leaves.Count>0)
{
db.Leaves.AddRange(leaves);
db.SaveChanges();
}
if you want to use async save you have to make async action at first.
The raison every time that foreach execute the savechnages there is a thread that your not note controlling. Since entity framework is managing the savechanges function. You have to execute your savechnages after the foreach or use async function.
here an example for the async:
private static async Task<Student> GetStudent()
{
Student student = null;
using (var context = new SchoolDBEntities())
{
Console.WriteLine("Start GetStudent...");
student = await (context.Students.Where(s => s.StudentID == 1).FirstOrDefaultAsync<Student>());
Console.WriteLine("Finished GetStudent...");
}
return student;
}
*This Code finally worked:
public ActionResult FeedTempdataToMainDB()
{
var leaves = new List<Leave>();
foreach (var item in db.TempLeaves)
{
var L = new Leave();
L.Pcode = Int32.Parse(item.Cod);
var z = int.Parse(item.LT) - 1;
if (z == 0) L.LT = Leave.LeaveType.Saati;
else L.LT = Leave.LeaveType.Roozane;
var o = int.Parse(item.DLT);
if (o == 0) L.DLT = Leave.DLType.Estehghaghi;
if (o == 1) L.DLT = Leave.DLType.Estelaji;
else L.DLT = Leave.DLType.Bihoghoogh;
L.LeaveDayStart = item.LeaveDayStart.Old6digToMiladi();
L.LeaveDayEnd = item.LeaveDayEnd.Old6digToMiladi();
L.LeaveTimeStart = StringToHour(item.LeaveTimeStart);
L.LeaveTimeEnd = StringToHour(item.LeaveTimeEnd);
L.LeaveDays = int.Parse(item.LeaveDays);
L.LeaveMinuts = SaatiLengh(item.LeaveMinuts);
L.RegDate = StringToHour(item.RegTime);
L.RegDate = item.RegDate.Old6digToMiladi().Date;
L.RegistrarCode = Int32.Parse(item.RegistrarCode);
L.HijriYear = L.LeaveDayStart.GetHijriYear();
var t = IsOk(item.RegTime);
if (L.DLT == 0 && t == false || L.LT == 0 && t == false)
{
L.Calculate = false;
L.IsActive = false;
}
else { L.Calculate = true; L.IsActive = true; }
leaves.Add(L);
}
if (leaves.Count > 0)
{
db.Leaves.AddRange(leaves);
db.SaveChanges();
}
return RedirectToAction("index");
}

Acumatica: Ability to override DefaultEndpointImpl to add advanced custom logic to contract REST API

I'm wondering if it possible to override DefaultEndpointImpl.cs or add my own API logic in another file?
I'm struggling with a few API calls which require the logic in this file to be overridden or added to. For example I am able to create a purchase receipt for a PO via the api successfully, however I'm not able to add a "Transfer Receipt" purchase receipt in the same way.
I've included various non-standard fields to the API endpoints that reference the original transfer, transfer order and shipment but have been unsuccessful. The API calls succeeds but no lines are added. I've been able to get lines to update their quantity once generated but can't add or delete current lines.
The problem looks to stem from this code, which seems to add functionality that correctly handles adding Purchase order lines logic of the graph but doesn't do anything special for other receipt types.
[FieldsProcessed(new[] { "POLineNbr", "POOrderType", "POOrderNbr" })]
protected void PurchaseReceiptDetail_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity) {
var receiptEntry = (POReceiptEntry)graph;
var lineNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "POLineNbr") as EntityValueField;
var orderType = targetEntity.Fields.SingleOrDefault(f => f.Name == "POOrderType") as EntityValueField;
var orderNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "POOrderNbr") as EntityValueField;
bool insertViaAddPO = lineNbr != null && orderNbr != null && orderType != null;
if (!insertViaAddPO && (lineNbr != null || orderType != null || orderNbr != null)) {
throw new PXException(PO.Messages.POTypeNbrLineNbrMustBeFilled);
}
var detailsCache = receiptEntry.transactions.Cache;
if (insertViaAddPO) {
receiptEntry.filter.Cache.Remove(receiptEntry.filter.Current);
receiptEntry.filter.Cache.Insert(new POReceiptEntry.POOrderFilter());
var filter = receiptEntry.filter.Current; var state = receiptEntry.filter.Cache.GetStateExt(filter, "OrderType") as PXStringState;
if (state != null && state.AllowedLabels.Contains(orderType.Value)) {
orderType.Value = state.ValueLabelDic.Single(p => p.Value == orderType.Value).Key;
}
receiptEntry.filter.Cache.SetValueExt(filter, "OrderType", orderType.Value);
receiptEntry.filter.Cache.SetValueExt(filter, "OrderNbr", orderNbr.Value);
receiptEntry.filter.Update(filter);
var orders = receiptEntry.poLinesSelection.Select().Select(r => r.GetItem<POReceiptEntry.POLineS>());
var order = orders.FirstOrDefault(o => o.LineNbr == int.Parse(lineNbr.Value));
if (order == null) {
throw new PXException(PO.Messages.PurchaseOrderLineNotFound);
}
order.Selected = true;
receiptEntry.poLinesSelection.Update(order);
receiptEntry.Actions["AddPOOrderLine2"].Press();
} else {
detailsCache.Current = detailsCache.Insert();
}
}
After a lot of trial and error I have managed to get everything working as I need. However I'm concerned that since this is not documented information that it may be subject to change in the near future.
The methods in the class DefaultEndpointImpl are called via reflection. To add custom functionality for my default endpoint I have extended the default class and added the necessary attributes to my class and functions.
My custom class adds the following:
Overides the default PurchaseReceiptDetail_Insert function to add transfer receipt functionality.
Adds ReceiptDetail_Insert method to allow adding an IN receipt referencing
The first one was pretty straight forward and I'm happy with the outcome. The second one took a lot of time and debugging to get right, is hacky and probably doesn't work with serial tracked items. The reason it's taken so long is because there are many unknowns and I've essentially been guessing based on the code in the base class. For example I'm not even sure at which stage this function fires. It looks the functions completely override some other default logic which is invisible.
So take it or leave it! Maybe I will reach out to Acumatica to see if I can get more information.
using PX.Api;
using PX.Api.ContractBased;
using PX.Api.ContractBased.Models;
using PX.Data;
using PX.Objects.PO;
using PX.Objects.IN;
using System;
using System.Linq;
using PX.Objects.CM;
using PX.Objects.CS;
namespace AcuStock
{
[PXVersion("5.30.001", "AcuStock")]
[PXVersion("6.00.001", "AcuStock")]
[PXVersion("17.200.001", "AcuStock")]
public class AcuStockEndpointImpl : PX.Objects.DefaultEndpointImpl
{
[FieldsProcessed(new[] { "POLineNbr", "POOrderType", "POOrderNbr", "OrigLineNbr", "OrigRefNbr" })]
protected new void PurchaseReceiptDetail_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity){
var lineNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "OrigLineNbr") as EntityValueField;
var refNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "OrigRefNbr") as EntityValueField;
var receiptQty = targetEntity.Fields.SingleOrDefault(f => f.Name == "ReceiptQty") as EntityValueField;
var location = targetEntity.Fields.SingleOrDefault(f => f.Name == "Location") as EntityValueField;
var inventoryID = targetEntity.Fields.SingleOrDefault(f => f.Name == "InventoryID") as EntityValueField;
bool insertViaAddTR = lineNbr != null && refNbr != null;
var receiptEntry = (POReceiptEntry) graph;
if (insertViaAddTR){
receiptEntry.addReceipt.Cache.Remove(receiptEntry.addReceipt.Current);
receiptEntry.addReceipt.Cache.Insert(new POReceiptEntry.POReceiptLineS());
var filter = receiptEntry.addReceipt.Current;
receiptEntry.addReceipt.Cache.SetValueExt(filter, "OrigRefNbr", refNbr.Value);
receiptEntry.addReceipt.Cache.SetValueExt(filter, "OrigLineNbr", lineNbr.Value);
receiptEntry.addReceipt.Cache.SetValueExt(filter, "InventoryID", inventoryID.Value);
receiptEntry.addReceipt.Cache.SetValueExt(filter, "ReceiptQty", receiptQty.Value);
if (location != null)
receiptEntry.addReceipt.Cache.SetValueExt(filter, "LocationID", location.Value);
receiptEntry.addReceipt.Update(filter);
var lines = receiptEntry.addReceipt.Select().Select(r => r.GetItem<POReceiptEntry.POReceiptLineS>());
var line = lines.FirstOrDefault(o => o.OrigLineNbr == int.Parse(lineNbr.Value));
if (line == null){
throw new PXException(PX.Objects.PO.Messages.PurchaseOrderLineNotFound);
}
receiptEntry.addPOReceiptLine2.Press();
} else {
base.PurchaseReceiptDetail_Insert(graph, entity, targetEntity);
}
var allocations = (targetEntity.Fields.SingleOrDefault(f => string.Equals(f.Name, "Allocations")) as EntityListField).Value ?? new EntityImpl[0];
if (allocations.Any(a => a.Fields != null && a.Fields.Length > 0)){
// Remove automatically added allocation
if (receiptEntry.splits.Current != null){
receiptEntry.splits.Delete(receiptEntry.splits.Current);
}
}
}
[FieldsProcessed(new[] { "OrigLineNbr", "OrigRefNbr", "Quantity", "Location" })]
protected void ReceiptDetails_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity) {
var lineNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "OrigLineNbr") as EntityValueField;
var receiptQty = targetEntity.Fields.SingleOrDefault(f => f.Name == "Quantity") as EntityValueField;
var location = targetEntity.Fields.SingleOrDefault(f => f.Name == "Location") as EntityValueField;
var allocations = (targetEntity.Fields.SingleOrDefault(f => string.Equals(f.Name, "Allocations")) as EntityListField).Value ?? new EntityImpl[0];
var hasAllocations = allocations.Any(a => a.Fields != null && a.Fields.Length > 0);
var receiptEntry = (INReceiptEntry) graph;
string transferNbr = receiptEntry.receipt.Current.TransferNbr;
var detailsCache = receiptEntry.transactions.Cache;
if (lineNbr == null || transferNbr == null){
detailsCache.Current = detailsCache.Insert();
return;
}
INTran newtran = null;
decimal newtranqty = Decimal.Parse(receiptQty.Value);
decimal newtrancost = 0m;
receiptEntry.ParseSubItemSegKeys();
using (new PXReadBranchRestrictedScope())
{
foreach (PXResult<INTransitLine, INLocationStatus2, INTransitLineLotSerialStatus, INSite, InventoryItem, INTran> res in
PXSelectJoin<INTransitLine,
InnerJoin<INLocationStatus2, On<INLocationStatus2.locationID, Equal<INTransitLine.costSiteID>>,
LeftJoin<INTransitLineLotSerialStatus,
On<INTransitLine.transferNbr, Equal<INTransitLineLotSerialStatus.transferNbr>,
And<INTransitLine.transferLineNbr, Equal<INTransitLineLotSerialStatus.transferLineNbr>>>,
InnerJoin<INSite, On<INSite.siteID, Equal<INTransitLine.toSiteID>>,
InnerJoin<InventoryItem, On<InventoryItem.inventoryID, Equal<INLocationStatus2.inventoryID>>,
InnerJoin<INTran,
On<INTran.docType, Equal<INDocType.transfer>,
And<INTran.refNbr, Equal<INTransitLine.transferNbr>,
And<INTran.lineNbr, Equal<INTransitLine.transferLineNbr>,
And<INTran.invtMult, Equal<shortMinus1>>>>>>>>>>,
Where<INTransitLine.transferNbr, Equal<Required<INTransitLine.transferNbr>>, And<INTransitLine.transferLineNbr, Equal<Required<INTransitLine.transferLineNbr>>>>,
OrderBy<Asc<INTransitLine.transferNbr, Asc<INTransitLine.transferLineNbr>>>>
.Select(receiptEntry, transferNbr, lineNbr.Value))
{
INTransitLine transitline = res;
INLocationStatus2 stat = res;
INTransitLineLotSerialStatus lotstat = res;
INSite site = res;
InventoryItem item = res;
INTran tran = res;
if (stat.QtyOnHand == 0m || (lotstat != null && lotstat.QtyOnHand == 0m))
continue;
if (newtran == null) {
if (!object.Equals(receiptEntry.receipt.Current.BranchID, site.BranchID))
{
INRegister copy = PXCache<INRegister>.CreateCopy(receiptEntry.receipt.Current);
copy.BranchID = site.BranchID;
receiptEntry.receipt.Update(copy);
}
newtran = PXCache<INTran>.CreateCopy(tran);
newtran.OrigBranchID = newtran.BranchID;
newtran.OrigTranType = newtran.TranType;
newtran.OrigRefNbr = transitline.TransferNbr;
newtran.OrigLineNbr = transitline.TransferLineNbr;
newtran.BranchID = site.BranchID;
newtran.DocType = receiptEntry.receipt.Current.DocType;
newtran.RefNbr = receiptEntry.receipt.Current.RefNbr;
newtran.LineNbr = (int)PXLineNbrAttribute.NewLineNbr<INTran.lineNbr>(receiptEntry.transactions.Cache, receiptEntry.receipt.Current);
newtran.InvtMult = (short)1;
newtran.SiteID = transitline.ToSiteID;
newtran.LocationID = transitline.ToLocationID;
newtran.ToSiteID = null;
newtran.ToLocationID = null;
newtran.BaseQty = 0m;
newtran.Qty = 0m;
newtran.UnitCost = 0m;
newtran.Released = false;
newtran.InvtAcctID = null;
newtran.InvtSubID = null;
newtran.ReasonCode = null;
newtran.ARDocType = null;
newtran.ARRefNbr = null;
newtran.ARLineNbr = null;
newtran.ProjectID = null;
newtran.TaskID = null;
newtran.CostCodeID = null;
newtran.TranCost = 0m;
receiptEntry.splits.Current = null;
newtran = receiptEntry.transactions.Insert(newtran);
receiptEntry.transactions.Current = newtran;
if (receiptEntry.splits.Current != null)
{
receiptEntry.splits.Delete(receiptEntry.splits.Current);
}
}
if (hasAllocations){
newtranqty = 0m;
foreach (var allocation in allocations) {
var newsplitqty = allocation.Fields.SingleOrDefault(f => f.Name == "Quantity") as EntityValueField;
var newsplitlocation = allocation.Fields.SingleOrDefault(f => f.Name == "Location") as EntityValueField;
INTranSplit newsplit = this.addReceiptSplitLine(receiptEntry, stat, lotstat, transitline, newtran, item, Decimal.Parse(newsplitqty.Value), newsplitlocation.Value);
newtrancost += newsplit.BaseQty.Value * newsplit.UnitCost.Value;
newtranqty += newsplit.BaseQty.Value;
}
break;
} else {
INTranSplit newsplit = this.addReceiptSplitLine(receiptEntry, stat, lotstat, transitline, tran, item, newtranqty, null);
newtrancost += newsplit.BaseQty.Value * newsplit.UnitCost.Value;
newtranqty += newsplit.BaseQty.Value;
}
}
receiptEntry.UpdateTranCostQty(newtran, newtranqty, newtrancost);
}
}
[FieldsProcessed(new[] { "OrigLineNbr" })]
protected void ReceiptAllocations_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity) {
// no-op
}
private INTranSplit addReceiptSplitLine(INReceiptEntry receiptEntry, INLocationStatus2 stat, INTransitLineLotSerialStatus lotstat, INTransitLine transitline, INTran tran, InventoryItem item, Decimal qty, string location){
INTranSplit newsplit;
decimal newsplitqty;
if (lotstat.QtyOnHand == null)
{
newsplit = new INTranSplit();
newsplit.InventoryID = stat.InventoryID;
newsplit.IsStockItem = true;
newsplit.FromSiteID = transitline.SiteID;
newsplit.SubItemID = stat.SubItemID;
newsplit.LotSerialNbr = null;
newsplitqty = qty;
}
else
{
newsplit = new INTranSplit();
newsplit.InventoryID = lotstat.InventoryID;
newsplit.IsStockItem = true;
newsplit.FromSiteID = lotstat.FromSiteID;
newsplit.SubItemID = lotstat.SubItemID;
newsplit.LotSerialNbr = lotstat.LotSerialNbr;
newsplitqty = qty;
}
newsplit.DocType = receiptEntry.receipt.Current.DocType;
newsplit.RefNbr = receiptEntry.receipt.Current.RefNbr;
newsplit.LineNbr = tran.LineNbr;
newsplit.SplitLineNbr = (int)PXLineNbrAttribute.NewLineNbr<INTranSplit.splitLineNbr>(receiptEntry.splits.Cache, receiptEntry.receipt.Current);
newsplit.UnitCost = 0m;
newsplit.InvtMult = (short)1;
newsplit.SiteID = transitline.ToSiteID;
newsplit.PlanID = null;
newsplit.Released = false;
newsplit.ProjectID = null;
newsplit.TaskID = null;
if (location == null) {
newsplit.LocationID = lotstat.ToLocationID ?? transitline.ToLocationID;
} else {
receiptEntry.splits.SetValueExt<INTranSplit.locationID>(newsplit, location);
}
newsplit = receiptEntry.splits.Insert(newsplit);
newsplit.MaxTransferBaseQty = newsplitqty;
newsplit.BaseQty = newsplitqty;
newsplit.Qty = newsplit.BaseQty.Value;
receiptEntry.UpdateCostSubItemID(newsplit, item);
receiptEntry.SetCostAttributes(tran, newsplit, item, tran.OrigRefNbr);
newsplit.UnitCost = PXCurrencyAttribute.BaseRound(receiptEntry, newsplit.UnitCost);
receiptEntry.splits.Update(newsplit);
return newsplit;
}
}
}

How to handle NoNullAllowedException in try/catch?

I have a form in C# for inputting some data into a List.
The form consists of text boxes and up and down numeric boxes. Everything works fine but I want to have an error handler (try/catch) in my code so it will check if any of the text boxes are empty or the numeric boxes are left to 0, if thats the case it should pop up an error message.
I tried :
try
{
//code
}
catch (NoNullAllowedException e) //tried it without the e as well
{
//code
}
The code I was having in the brackets its the following one. Sometimes the GetItemDetails() was throwing me an error saying that not all code paths returns a value.
Any thoughts why is doing this or how can I fix it?
public iRepairable GetItemDetails()
{
Shirt shirt = null;
TShirt tshirt = null;
Trouser trouser = null;
Shoe shoe = null;
Boolean isShirt = true;
Boolean isTshirt = true;
Boolean isTrouser = true;
Boolean isShoe = true;
if (rdoShirt.Checked == true)
{
shirt = new Shirt(txtBrand.Text, Convert.ToDouble(txtPrice.Text), Convert.ToInt32(txtAmount.Text), txtCollection.Text);
isTshirt = false;
isTrouser = false;
isShoe = false;
}
else if (rdoTShirt.Checked == true)
{
tshirt = new TShirt(txtBrand.Text, Convert.ToDouble(txtPrice.Text), Convert.ToInt32(txtAmount.Text), txtCollection.Text);
isShirt = false;
isTrouser = false;
isShoe = false;
}
else if (rdoTrouser.Checked == true)
{
trouser = new Trouser(txtBrand.Text, Convert.ToDouble(txtPrice.Text), Convert.ToInt32(txtAmount.Text), txtCollection.Text);
isShirt = false;
isTshirt = false;
isShoe = false;
}
else
{
shoe = new Shoe(txtBrand.Text, Convert.ToDouble(txtPrice.Text), Convert.ToInt32(txtAmount.Text), txtCollection.Text);
isShirt = false;
isTrouser = false;
isTshirt = false;
}
if (isShirt)
{
return shirt;
}
else if (isTshirt)
{
return tshirt;
}
else if (isTrouser)
{
return trouser;
}
else //if(isShoe)
{
return shoe;
}
First of all, the NoNullAllowedException is not for list or just null values. Is the exception that throws when you want to insert null values in a column that doesn't allow them (for more info, MSDN).
For your code, place at the bottom of your code a default return value (but as far as i can see, your code shouldnt break at all)

LinQ query, only one record submitted/inserted

I'm trying to insert only males teachers into the "MaleTeachers" table, but after program is executed I see only one teacher in that table. In addition, I have more then one teacher in the "Stuffs" table, but inserted one is the last that matches "if" criteria. Could you correct this code please. Service implementation:
public void AddTeachers()
{
DataClasses1DataContext data = new DataClasses1DataContext();
DataClasses2DataContext data2 = new DataClasses2DataContext();
MaleTeacher tchr = new MaleTeacher();
foreach (var d in data.Stuffs)
{
if (d.stuffSex == true && d.stuffJob == "Teacher")
{
tchr.teacherName = d.stuffName;
tchr.teacherAge = d.stuffAge;
tchr.teacherJob = d.stuffJob;
tchr.teacherDepartm = "geology";
data2.MaleTeachers.InsertOnSubmit(tchr);
}
}
data2.SubmitChanges();
}
you foreach loop should be.
foreach (var d in data.Stuffs)
{
if (d.stuffSex == true && d.stuffJob == "Teacher")
{
MaleTeacher tchr = new MaleTeacher();
tchr.teacherName = d.stuffName;
tchr.teacherAge = d.stuffAge;
tchr.teacherJob = d.stuffJob;
tchr.teacherDepartm = "geology";
data2.MaleTeachers.InsertOnSubmit(tchr);
}
}
You are creating only one intance and then modifying it again and again... instead you should create a different MaleTeacher instance on every time.
MaleTeacher tchr = new MaleTeacher();
foreach (var d in data.Stuffs)
{
if (d.stuffSex == true && d.stuffJob == "Teacher")
{
tchr.teacherName = d.stuffName;
tchr.teacherAge = d.stuffAge;
tchr.teacherJob = d.stuffJob;
tchr.teacherDepartm = "geology";
data2.MaleTeachers.InsertOnSubmit(tchr);
tchr = new MaleTeacher();
}
}

Categories