I am new in coding and I am having the following issue. When I run the select if there are no rows I receive the following error
but in that case, i want to make an insert
how can I do this? This is my entire code:
private DataRow verifica_pontajul()
{
string query = String.Format("select PR_ID,WORKER_Name,PR_Come,PR_Go, CURRENT_TIMESTAMP from `ppresence` {0}",
(Functii.marca == "admin" ? "" :
String.Format("WHERE PR_WorkerPTR='{0}' ORDER BY PR_ID DESC LIMIT 1 ", this.marca)
));
return conn.dt(query,0).Rows[0];
}
public class liniepontaj
{
public long idlinie = 0;
private string angajat = "";
public DateTime DataIntrare = new DateTime();
private DateTime DataIesire = new DateTime();
public DateTime DataReferinta = new DateTime();
private bool isIntrare = false;
public bool facintrare = false;
public bool faciesire = false;
public liniepontaj() { }
public liniepontaj(DataRow rand)
{
this.idlinie = long.Parse(rand.ItemArray[0].ToString());
this.angajat = rand.ItemArray[1].ToString();
this.DataIntrare = (DateTime)rand.ItemArray[2];
try {
this.DataIesire = (DateTime)rand.ItemArray[3];
}
catch (Exception) { this.DataIesire = new DateTime(1, 1, 1, 0, 0, 0); }
this.DataReferinta = (DateTime)rand.ItemArray[4];
if (this.DataIesire == null || this.DataIesire != new DateTime(1, 1, 1, 0, 0, 0)) { isIntrare = true; } else { isIntrare = false; }
TimeSpan t1 = DataReferinta - DataIntrare;
TimeSpan t2 = DataReferinta - DataIesire;
if ((t1.TotalMinutes < 15 && !this.isIntrare))
{
faciesire = false;
facintrare = false;
}
else if (t2.TotalMinutes < 15 && this.isIntrare)
{
faciesire = false;
facintrare = false;
}
else
{
facintrare = isIntrare;
faciesire = !isIntrare;
}
}
}
Where should i modify? To have the properly insert functional?
Basically, you just need to validate if there is any data inside Rows.
var dt = conn.dt(query, 0);
if (dt.Rows.Count == 0) return null;
else return dt.Rows[0];
Check for rowcount and if greater than or equal to 1 and then proceed else insert
Related
I have a User Control with a DataGrid.Every thing was fine since the DataGride Pagenation Function within the User Control Class.I Desided to move the pagenation functions into a class instead.This is my Code
{
private static DataTable _dt ;
private static TextBlock _PageInformation;
private static ComboBox _NumberOfRecords;
private static Button _btnPrev;
private static Button _BtnFirst;
private static Button _BtnNext;
private static Button _BtnLast;
internal static AssetsManagement equipmentManage
{
get { return equipmentMng; }
set { equipmentMng = value; }
}
private static DataGrid _datagridObject;
public static TextBlock PageInformation { get => _PageInformation; set => _PageInformation = value; }
public static DataTable dt { get => _dt; set => _dt = value; }
public static ComboBox NumberOfRecords { get => _NumberOfRecords; set => _NumberOfRecords = value; }
public static DataGrid DatagridObject { get => _datagridObject; set => _datagridObject = value; }
public static Button BtnPrev { get => _btnPrev; set => _btnPrev = value; }
public static Button BtnFirst { get => _BtnFirst; set => _BtnFirst = value; }
public static Button BtnNext { get => _BtnNext; set => _BtnNext = value; }
public static Button BtnLast { get => _BtnLast; set => _BtnLast = value; }
int pageIndex = 1;
public static int numberOfRecPerPage;
//To check the paging direction according to use selection.
private enum PagingMode
{ First = 1, Next = 2, Previous = 3, Last = 4, PageCountChange = 5 };
public Pagenation(DataGrid UCDatagrid,ComboBox NumberOfRecordsComboBox,TextBlock PageInfo,DataTable Data,Button Prev, Button First, Button Next, Button Last)
{
DatagridObject = UCDatagrid;
dt = Data.Copy();
if (Data == null)
{
MessageBox.Show(Data.Rows.Count.ToString());
}
PageInformation = PageInfo;
NumberOfRecords = NumberOfRecordsComboBox;
Prev = BtnPrev;
First = BtnFirst;
Next= BtnNext;
Last= BtnLast;
NumberOfRecordsComboBox.Items.Add("5");
NumberOfRecordsComboBox.Items.Add("10");
NumberOfRecordsComboBox.Items.Add("15");
NumberOfRecordsComboBox.Items.Add("20");
NumberOfRecordsComboBox.Items.Add("25");
RefreshDataGrid(dt);
}
public void BtnFirst_Click(object sender, RoutedEventArgs e)
{
Navigate((int)PagingMode.First);
}
public void BtnNext_Click()
{
Navigate((int)PagingMode.Next);
}
public void BtnPrev_Click(object sender, RoutedEventArgs e)
{
Navigate((int)PagingMode.Previous);
}
public void BtnLast_Click(object sender, RoutedEventArgs e)
{
Navigate((int)PagingMode.Last);
}
public void CbNumberOfRecords_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Navigate((int)PagingMode.PageCountChange);
}
private void Navigate(int mode)
{
int count;
switch (mode)
{
case (int)PagingMode.Next:
BtnPrev.IsEnabled = true;
BtnFirst.IsEnabled = true;
if (dt.Rows.Count >= (pageIndex * numberOfRecPerPage))
{
if (dt.AsEnumerable().Skip(pageIndex *
numberOfRecPerPage).Take(numberOfRecPerPage).Count() == 0)
{
DatagridObject.ItemsSource = null;
DatagridObject.ItemsSource = dt.Rows.Count <= 0 ? null : dt.AsEnumerable().Skip((pageIndex *
numberOfRecPerPage) - numberOfRecPerPage).Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
count = (pageIndex * numberOfRecPerPage) +
(dt.AsEnumerable().Skip(pageIndex *
numberOfRecPerPage).Take(numberOfRecPerPage)).Count();
}
else
{
DatagridObject.ItemsSource = null;
DatagridObject.ItemsSource = dt.Rows.Count <= 0 ? null : dt.AsEnumerable().Skip(pageIndex *
numberOfRecPerPage).Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
count = (pageIndex * numberOfRecPerPage) +
(dt.AsEnumerable().Skip(pageIndex * numberOfRecPerPage).Take(numberOfRecPerPage)).Count();
pageIndex++;
}
PageInformation.Text = count + " of " + dt.Rows.Count;
}
else
{
BtnNext.IsEnabled = false;
BtnLast.IsEnabled = false;
}
break;
case (int)PagingMode.Previous:
BtnNext.IsEnabled = true;
BtnLast.IsEnabled = true;
if (pageIndex > 1)
{
pageIndex -= 1;
DatagridObject.ItemsSource = null;
if (pageIndex == 1)
{
DatagridObject.ItemsSource = dt.Rows.Count <= 0 ? null : dt.AsEnumerable().Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
count = dt.AsEnumerable().Take(numberOfRecPerPage).Count();
PageInformation.Text = count + " of " + dt.Rows.Count;
}
else
{
DatagridObject.ItemsSource = dt.Rows.Count <= 0 ? null : dt.AsEnumerable().Skip
(pageIndex * numberOfRecPerPage).Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
count = Math.Min(pageIndex * numberOfRecPerPage, dt.Rows.Count);
PageInformation.Text = count + " of " + dt.Rows.Count;
}
}
else
{
BtnPrev.IsEnabled = false;
BtnFirst.IsEnabled = false;
}
break;
case (int)PagingMode.First:
pageIndex = 2;
Navigate((int)PagingMode.Previous);
break;
case (int)PagingMode.Last:
pageIndex = (dt.Rows.Count / numberOfRecPerPage);
Navigate((int)PagingMode.Next);
break;
case (int)PagingMode.PageCountChange:
numberOfRecPerPage = Convert.ToInt32(NumberOfRecords.SelectedItem);
DatagridObject.ItemsSource = null;
DatagridObject.ItemsSource = dt.Rows.Count <= 0 ? null : dt.AsEnumerable().Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
count = (dt.AsEnumerable().Take(numberOfRecPerPage)).Count();
PageInformation.Text = count + " of " + dt.Rows.Count;
BtnNext.IsEnabled = true;
BtnLast.IsEnabled = true;
BtnPrev.IsEnabled = true;
BtnFirst.IsEnabled = true;
break;
}
}
public static void RefreshDataGrid(DataTable dte)
{
MessageBox.Show(dte.Rows.Count.ToString());
dt = dte.Copy();
MessageBox.Show(dt.Rows.Count.ToString());
DatagridObject.ItemsSource = null;
DatagridObject.ItemsSource = dt.AsEnumerable().Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
int count = dt.AsEnumerable().Take(numberOfRecPerPage).Count();
PageInformation.Text = count + " of " + dt.Rows.Count;
}
}}
and in the Class of the UserControl I instantaite an object of the Pagenation Class with the constructor that takes all the needed varaible for pagenation.
public PartsUC()
{
InitializeComponent();
PartsDataTable = PartMng.GetAllEquipments();
MessageBox.Show(PartsDataTable.Rows.Count.ToString());
PageInformation = lblpageInformation;
Partsdatagrid = this.PartsDataGrid;
CbNumberOfRecords = this.cbNumberOfRecords;//the interface XAMAL Combobox
Pagenation pagenation = new Pagenation(Partsdatagrid, cbNumberOfRecords, PageInformation, PartsDataTable, btnPrev, btnFirst, btnNext, btnLast);
//Pagenation.RefreshDataGrid(PartsDataTable);}
The problem is that i still getting this error message!
The source contains no DataRows
and the error points to the refreshDataGrid method in this line
DatagridObject.ItemsSource = dt.AsEnumerable().Take(numberOfRecPerPage).CopyToDataTable().DefaultView;
Note that the messege box in the function refreshDataGrid shows that i have 50 rows.
Solved it,The thing that caused the error was the function Take() since it takes the number from the combobox that let you choose how many rows to display.I put Fixed number and It Worked.
DatagridObject.ItemsSource = dt.AsEnumerable().Take(15).CopyToDataTable().DefaultView;
I have checked all answer related to this error but I couldn't solve it.
I have an admission form. They are fields like DateOfAdmission, PhoneNumber **, **TimeOfAdmission and other things . When I try to retrieve values from the form and convert them. And then try to insert them in SQL Server Database. The application breaks saying...
'System.FormatException'
When parsing a string into DateTime, parse the string to take data before putting each variable into the DateTime Object.
Here is my code please look at it and tell me where I am getting wrong.
public partial class AdmissionForm : Window
{
public AdmissionForm()
{
InitializeComponent();
}
private void SubmitFormClick(object sender, RoutedEventArgs e)
{
// Parsing Values
// STIRNG TO INT
int AdmissionNumber = int.Parse(AdmissionNumberTextBox.Text);
int CNIC = int.Parse(CNICTextBox.Text);
int Age = int.Parse(AgeTextBox.Text);
int PhoneNumber = int.Parse(PhoneTextBox.Text);
int MobileNumber = int.Parse(MobileTextBox.Text);
int EmergencyNumber = int.Parse(EmergencyTextBox.Text);
// Converting time 'String' into Byte[]
//string time = DateTime.Now.ToString("hh:mm:tt"); //TimeOfDay.ToString("HH:mm:ss")
byte[] TimeOfAdmission = Encoding.ASCII.GetBytes(DateTime.Now.ToString("hh:mm:tt"));
// Converting date 'String' into DateTime
//string date = DateTime.Now.ToString("dd/MM/yyyy");
DateTime DateOfAdmission = Convert.ToDateTime(DateTime.Now.ToString("dd/MM/yyyy"));
// String
var StudentName = StudentNameTextBox.Text;
var FatherName = FatherNameTextBox.Text;
var Qualification = QualificationTextBox.Text;
var Nationality = NationalityTextBox.Text;
var Adress = AdressTextBox.Text;
var Timing = SheduleTime.SelectedValue.ToString();
var ClassLevel = ClassValue.SelectedValue.ToString();
var Reference = ReferenceTextBox.Text;
// DB context Getting Entites and attributes
var context = new AcademyEntities();
// Creating new Model
var Model = new StudentTable();
// Getting and Setting values
// Reading Values
Model.StudentName = StudentName;
Model.FatherName = FatherName;
Model.StudentCNIC = CNIC;
Model.GuardianName = null;
Model.Nationality = Nationality;
Model.Qualification = Qualification;
Model.StudentAge = Age;
Model.AdmissionNumber = AdmissionNumber;
Model.TimeOfAdmission = TimeOfAdmission;
Model.DateOfAdmission = DateOfAdmission;
Model.MobileNumber = MobileNumber;
Model.PhoneNumber = PhoneNumber;
Model.EmergencyNumber = EmergencyNumber;
Model.Adress = Adress;
Model.ClassID = ClassTime(Timing);
Model.CourseLevelID = CourseLevelID(ClassLevel);
Model.Reference = Reference;
context.StudentTables.Add(Model);
context.SaveChanges();
// Class Time Id
int ClassTime(string Timing)
{
int classId = 1;
if (Timing == "2 to 3 PM")
{
return classId;
}
else if (Timing == "3 to 4 PM")
{
classId = 2;
return classId;
}
else if (Timing == "4 to 5 PM")
{
classId = 3;
return classId;
}
else if (Timing == "5 to 6 PM")
{
classId = 4;
return classId;
}
else if (Timing == "6 to 7 PM")
{
classId = 5;
return classId;
}
return classId;
}
// Course Level Id
int CourseLevelID(string ClassLevel)
{
int courseLevelId = 1;
if (ClassLevel == "Lower Basic")
{
return courseLevelId;
}
else if (ClassLevel == "Basic")
{
courseLevelId = 2;
return courseLevelId;
}
else if (ClassLevel == "Pre Starter")
{
courseLevelId = 3;
return courseLevelId;
}
else if (ClassLevel == "Starter")
{
courseLevelId = 4;
return courseLevelId;
}
else if (ClassLevel == "Intermediate")
{
courseLevelId = 5;
return courseLevelId;
}
else if (ClassLevel == "Advance")
{
courseLevelId = 5;
return courseLevelId;
}
return courseLevelId;
}
}
Well I searched and found one solution to parse date as SQL SERVER timestamp
string currentTime = DateTime.Now.ToString("hh:mm:tt");
byte[] TimeOfAdmission = Encoding.ASCII.GetBytes(currentTime);
I don't know, if StackOverflow is the right place to ask about Performance issues, but I haven't found any better community for this issue yet.
Basically we have two sample programs, one is an addin and one is a winforms program referencing the Word interop.
Both have implemented the same method called GetTabsFromParagraph:
public class SlowExample
{
public static void GetTabsFromParagraph(Paragraph para, Style style, List<Tabulator> tabList, bool getTabsForCase = false)
{
foreach (TabStop tab in para.TabStops)
{
if (tab.CustomTab)
{
bool showTab = true;
foreach (TabStop ts in style.ParagraphFormat.TabStops)
{
if (Math.Abs(ts.Position - tab.Position) < 0.001 &&
ts.Alignment == tab.Alignment)
{
showTab = false;
break;
}
}
if (showTab || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung =
tab.Alignment == WdTabAlignment.wdAlignTabLeft
? TabulatorAusrichtung.Links
: TabulatorAusrichtung.Rechts,
Tabulatorart = TabulatorArt.Tabulator,
Position = tab.Position
};
tabList.Add(t);
}
}
}
if (!getTabsForCase)
{
foreach (TabStop ts in style.ParagraphFormat.TabStops)
{
if (ts.CustomTab)
{
bool showTab = true;
foreach (TabStop tab in para.TabStops)
{
if (Math.Abs(tab.Position - ts.Position) > 0.0001 || tab.Alignment != ts.Alignment)
{
showTab = false;
break;
}
}
if (showTab)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.Geloescht,
Tabulatorart = TabulatorArt.Tabulator,
Position = ts.Position
};
tabList.Add(t);
}
}
}
}
if (Math.Abs(para.LeftIndent - style.ParagraphFormat.LeftIndent) > 0.001 || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.Links,
Tabulatorart = TabulatorArt.Einzug,
Position = para.LeftIndent
};
tabList.Add(t);
}
if (Math.Abs(para.RightIndent - style.ParagraphFormat.RightIndent) > 0.001 || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.Rechts,
Tabulatorart = TabulatorArt.Einzug,
Position = para.RightIndent
};
tabList.Add(t);
}
if (Math.Abs(para.FirstLineIndent - style.ParagraphFormat.FirstLineIndent) > 0.001 || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung = TabulatorAusrichtung.ErstzeilenEinzug,
Tabulatorart = TabulatorArt.Einzug,
Position = para.FirstLineIndent
};
tabList.Add(t);
}
}
public class Tabulator
{
private TabulatorArt m_Tabulatorart;
private TabulatorAusrichtung m_Tabulatorausrichtung;
private float m_Position;
private bool m_UebernahmeInFolgedokument = false;
public float Position
{
get { return m_Position; }
set { m_Position = value; }
}
public float PositionOrg
{
get;
set;
}
public float PositionInCm
{
get
{
return (m_Position / 28.35F);
}
set
{
m_Position = value * 28.35F;
}
}
public TabulatorArt Tabulatorart
{
get { return m_Tabulatorart; }
set { m_Tabulatorart = value; }
}
public TabulatorAusrichtung Tabulatorausrichtung
{
get { return m_Tabulatorausrichtung; }
set { m_Tabulatorausrichtung = value; }
}
public TabulatorAusrichtung TabulatorausrichtungOrg
{
get;
set;
}
public bool UebernahmeInFolgedokument
{
get { return m_UebernahmeInFolgedokument; }
set { m_UebernahmeInFolgedokument = value; }
}
}
public enum TabulatorArt
{
Invalid = 0,
Tabulator = 1,
Einzug = 2
}
public enum TabulatorAusrichtung
{
Invalid = 0,
Links = 1,
Rechts = 2,
ErstzeilenEinzug = 3,
Geloescht = 4,
}
}
In each of the both programs, I load up a Application, open up a document with a few paragraphs and tabs and run this method for each paragraph like this:
private void TestSlowMethod(Word.Document document)
{
Word.Paragraphs documentParagraphs = document.Paragraphs;
List<Tabulator> tabList = new List<Tabulator>();
long swElapsedMilliseconds = 0;
foreach (Word.Paragraph documentParagraph in documentParagraphs)
{
Word.Style style = documentParagraph.get_Style();
Stopwatch sw = new Stopwatch();
sw.Start();
SlowExample.GetTabsFromParagraph(documentParagraph, style, tabList, true);
sw.Stop();
swElapsedMilliseconds += sw.ElapsedMilliseconds;
Debug.WriteLine(sw.ElapsedMilliseconds + "\r\n");
}
MessageBox.Show("Total ms: " + swElapsedMilliseconds);
Debug.WriteLine("Done...");
}
What I found out is the addin is running throw all of this 10-20 times faster.
Addin: 20-30 ms per call
WinForms tool: 200-300 ms per call
Why is that? My assumption would be, that the addin runs in the same context / process than the word application. But is that the real reason?
And can we fix that? Our software moved from addin to WPF + Interop-Word.
Thanks in advance!
Some performance fixes:
Check getTabsForCase sooner here:
if (tab.CustomTab)
{
bool showTab = true;
if (getTabsForCase) //insert this here, no need to run if getTabsForCase.
foreach (TabStop ts in style.ParagraphFormat.TabStops)
{
if (Math.Abs(ts.Position - tab.Position) < 0.001 &&
ts.Alignment == tab.Alignment)
{
showTab = false;
break;
}
}
if (showTab || getTabsForCase)
{
Tabulator t = new Tabulator
{
Tabulatorausrichtung =
tab.Alignment == WdTabAlignment.wdAlignTabLeft
? TabulatorAusrichtung.Links
: TabulatorAusrichtung.Rechts,
Tabulatorart = TabulatorArt.Tabulator,
Position = tab.Position
};
tabList.Add(t);
}
}
Similarly, put the check on getTabsForCase before all calculations in if statements:
//see getTabsForCase goes first
if (getTabsForCase || Math.Abs(para.LeftIndent - style.ParagraphFormat.LeftIndent) > 0.001)
Fix all of those conditionals to have getTabsForCase first - then the rest of the statement won't need to evaluate.
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
}
}
how to used the COM object for the lifetime in C#
I will be created the OPC server object, it will be used into the threading.timer this timer will be invoked at every seconds after the some time opcserver object, it will be release itself shoe the exception as " COM object that has been separated from its underlying RCW cannot be used.."
Here is the code
public partial class OPC_server : DevExpress.XtraEditors.XtraForm
{
private System.Threading.Timer timer1;
private System.Threading.Timer timer2;
parameter param = new parameter();//another class
private static readonly object myLockHolder = new object();
private static readonly object myLockHolder1 = new object();
public static OpcServer[] _opcServer;
private void OPC_server_Load(object sender, EventArgs e)
{
getconnectedOPC();
}
public void getconnectedOPC()
{
ds = opcconn.GetOPCServerInfo();
int i=0;
DataTable dtOPC=new DataTable();
if (ds.Tables[0].Rows.Count != 0 || ds.Tables[0] != null)
{
dtOPC = ds.Tables[0].Copy();
_opcServer = new OpcServer[dtOPC.Rows.Count];
TimeSpan delayTime = new TimeSpan(0, 0, 1);
TimeSpan intervalTime = new TimeSpan(0, 0, 0, 0, 450);
foreach (DataRow row in dtOPC.Rows)
{
if (i <= dtOPC.Rows.Count)
{
//connetion(row);
getconnect(i, row, dtOPC.Rows.Count);
i++;
}
}
connetion(dtOPC.Rows.Count);
}
}
//connecting the server
public void getconnect(int conn, DataRow r,int rows)
{
DataSet ds2=new DataSet();
DataTable dt2 = new DataTable();
try
{
string machinename = Convert.ToString(r["OPCIPAddress"]);
string servername = Convert.ToString(r["OPCName"]);
_opcServer[conn] = new OpcServer();
int i = _opcServer[conn].Connect(machinename, servername);
if (i == 0)
{
opcconn.update("true", servername);
writelog(servername, "connected");
}
else
{
opcconn.update("false", servername);
writelog(servername, "disconnected");
}
}
catch (OPCException e)
{
servername = Convert.ToString(r["OPCName"]);
opcconn.update("false", servername);
writelog(servername, e.Message.ToString());
}
catch (ApplicationException e)
{
servername = Convert.ToString(r["OPCName"]);
opcconn.update("false", servername);
writelog(servername, "No instance server");
}
}
public void OPCthread(DataRow r2,int timerinfo)
{
if (timerinfo == 0)
{
int rer = Convert.ToInt32(r2["refreshRate"]);//at least 1 second
TimeSpan dueTime = new TimeSpan(0, 0,0,0,rer);
TimeSpan interval = new TimeSpan(0, 0, 0 ,0 ,rer);
timer1 = new System.Threading.Timer(register, r2, dueTime,interval);
}
else if (timerinfo == 1)
{
TimeSpan dueTime;
TimeSpan interval;
int rer1 = Convert.ToInt32(r2["refreshRate"]);
dueTime = new TimeSpan(0, 0, 0, 0, rer1);
interval = new TimeSpan(0, 0, 0, 0, rer1);
timer2 = new System.Threading.Timer(register1, r2, dueTime, interval);
}
}
public void register(object row1)
{
try
{
lock (myLockHolder)
{
int cnt = 0, cnt1 = 0;
ItemValue[] rVals;
OPCItemDef[] item;
OpcServer srv = new OpcServer();
string[] array;
//SrvStatus status1;
DataSet paramds = new DataSet();
DataTable paramdt = new DataTable();
DataRow dt = (System.Data.DataRow)row1;
int serverID = Convert.ToInt32(dt["OPCServerID"]);
paramds = param.getparameter(Convert.ToInt32(dt["groupID"]));
if (Convert.ToBoolean(dt["setactive"]) == true)
{
if (paramds != null && paramds.Tables[0].Rows.Count != 0)
{
paramdt = paramds.Tables[0].Copy();
int tq = 0;
item = new OPCItemDef[paramdt.Rows.Count];
int clienthandle = 1;
foreach (DataRow r in paramdt.Rows)
{
if (tq < item.Length)
{
item[tq] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle, VarEnum.VT_EMPTY);
++clienthandle;
tq++;
}
}
array = new string[item.Length];
cnt1 = 0;
while (cnt1 < array.Length)
{
array[cnt1] = item[cnt1].ItemID;
cnt1++;
}
rVals = _opcServer[serverID - 1].Read(array, Convert.ToInt32(dt["refreshRate"]));
param.update(rVals, Convert.ToInt32(dt["groupID"]));
}
}
}
}
catch (ThreadAbortException) { }
finally { }
}
public void register1(object row2)
{
try
{
lock (myLockHolder1)
{
int cnt = 0, cnt11 = 0;
ItemValue[] rVals1;
OPCItemDef[] item1;
OpcServer srv1 = new OpcServer();
string[] array1;
DataSet paramds1 = new DataSet();
DataTable paramdt1 = new DataTable();
DataRow dt1 = (System.Data.DataRow)row2;
int serverID1 = Convert.ToInt32(dt1["OPCServerID"]);
// Boolean gstatus = grpclass.getstatus(Convert.ToInt32(dt["groupID"]));
paramds1 = param.getparameter2(Convert.ToInt32(dt1["groupID"]));
if (Convert.ToBoolean(dt1["setactive"]) == true)
{
if (paramds1 != null)
{
paramdt1 = paramds1.Tables[0].Copy();
int tq1 = 0;
item1 = new OPCItemDef[paramdt1.Rows.Count];
int clienthandle1 = 1;
foreach (DataRow r in paramdt1.Rows)
{
if (tq1 < item1.Length)
{
item1[tq1] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle1, VarEnum.VT_EMPTY);
clienthandle1++;
tq1++;
}
}
array1 = new string[item1.Length];
cnt11 = 0;
while (cnt11 < array1.Length)
{
array1[cnt11] = item1[cnt11].ItemID;
cnt11++;
}
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));
param.update1(rVals1, Convert.ToInt32(dt1["groupID"]));
}
}
}
}
catch { }
finally { }
}
please tell me the proper solution
When you are using OPC, you are using COM. Since you are also using a GUI, you are most likely using Single-Threaded Apartment (STA) for your ApartmentState. When this is the case, you should make sure that the OPC calls all happen on the thread that first instantiates the OPC object. Since the COM object is created on an STA thread, then it will try to marshal all the calls back onto that thread.
To make this work, you'll need to use a separate Thread instead of a System.Threading.Timer to do the OPC calls so that they are always on the same thread. The System.Threading.Timer callback will execute on a different thread (from the thread pool) every time (non-deterministic). You'll get better performance keeping it off the UI thread too, if the server is not responding, you'll get lack in the UI. Also, the server has the option of closing connections on a whim if it wants. You'll get an OPC Shutdown event that will tell you the server wants you to disconnect.