C# console App compare records to database - linq

I am parsing a flat file which is working line by line and inserting into the database but I want to add an additional step, actually additional 2 steps.
First I only want records for recalls for specific car manufacturers which I have a database table called AutoMake that has a list of all the makes I want to include. I need to compare the record to that table to ensure that it is a record of one of the makes that I want to include.
Then I need to do a second check to make sure the record is not already in my database.
This is a console App and I am using Entity for this. So here is my code I am driving myself crazy trying to write and rewrite this to include the checks but im just not getting it.
Oh and not that it really matters because if someone can get me in the right direction I can move from there but tokens[2] is the MAKETXT and RCL_CMPT_ID is tokens[23] and RCL_CMPT_ID can be used to verify if a record is already in the database since it is a unique value
public static void ParseTSV(string location)
{
Console.WriteLine("Parsing.....");
using (var reader = new StreamReader(location))
{
var lines = reader.ReadToEnd().Split(new char[] { '\n' });
if (lines.Length > 0)
{
foreach (string line in lines)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
var tokens = line.Trim().Split(new char[] { '\t' });
var recalls = new Recalls();
recalls.RECORD_ID = tokens[0];
recalls.CAMPNO = tokens[1];
recalls.MAKETXT = tokens[2];
recalls.MODELTXT = tokens[3];
recalls.YEARTXT = tokens[4];
recalls.MFGCAMPNO = tokens[5];
recalls.COMPNAME = tokens[6];
recalls.MFGNAME = tokens[7];
recalls.BGMAN = tokens[8];
recalls.ENDMAN = tokens[9];
recalls.RCLTYPECD = tokens[10];
recalls.POTAFF = tokens[11];
recalls.ODATE = tokens[12];
recalls.INFLUENCED_BY = tokens[13];
recalls.MFGTXT = tokens[14];
recalls.RCDATE = tokens[15];
recalls.DATEA = tokens[16];
recalls.RPNO = tokens[17];
recalls.FMVSS = tokens[18];
recalls.DESC_DEFECT = tokens[19];
recalls.CONEQUENCE_DEFECT = tokens[20];
recalls.CORRECTIVE_ACTION = tokens[21];
recalls.NOTES = tokens[22];
recalls.RCL_CMPT_ID = tokens[23];
string connectionString = GetConnectionString();
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmdIns = new SqlCommand(GetInsertSqlCust(recalls), connection);
connection.Open();
cmdIns.ExecuteNonQuery();
connection.Close();
cmdIns.Dispose();
cmdIns = null;
}
}
}
}
}

1:Get the ID to check against
2:Get the table where the search needs to be done like
string strExpression="";
(Datatable tdGeneric = dal.getsometable())
3:To check the auto make if exists:
if ( tdGeneric != null && tdGeneric.Rows.Count > 0)
{
strExpression = "tablecolumnsname = '" + recalls.MAKETXT + "' ";
tdGeneric.DefaultView.RowFilter = strExpression;
tdGeneric = tdGeneric.DefaultView.ToTable();
if (tdGeneric.Rows.Count > 0)
{
//make exist
}
else
make don't exists
}
else
{
make don't exist skip that text file's record
}
4: if make exist then check for a record if that exists in a table.
get the original table,search on that table for specific id in your case:
(Datatable tdGeneric2 = dal.getsometable())
if ( tdGeneric2 != null && tdGeneric.Rows.Count > 0)
{
strExpression = "tablecolumnsname = '" + recalls.RCL_CMPT_ID + "' ";
tdGeneric2.DefaultView.RowFilter = strExpression;
tdGeneric2 = tdGeneric2.DefaultView.ToTable();
if (tdGeneric2.Rows.Count > 0)
{
//record exist
}
else
record don't exists
}
else
{
record don't exist insert the record, or some flag to insert a record
}

You can take advantages of caching. Fetch all the Makes before reading the file and do a lookup in the List or Dictionary of existing AutoMakes to check if the AutoMake already exists in database or it is a new one. If the AutoMake is new, insert the record in database and also add the make in List\Dictionary. If AutoMake already exists, skip the line and move to next line.

Related

How to retrieve column names from a excel sheet?

Using EPPlus I'm writing data to multiple sheets. If a sheet is not created I'm adding a sheet else I'm retrieving the used rows and adding data from that row and saving it
FileInfo newFile = new FileInfo("Excel.xlsx");
using (ExcelPackage xlPackage = new ExcelPackage(newFile))
{
var ws = xlPackage.Workbook.Worksheets.FirstOrDefault(x => x.Name == language.Culture);
if (ws == null)
{
worksheet = xlPackage.Workbook.Worksheets.Add(language.Culture);
//writing data
}
else
{
worksheet = xlPackage.Workbook.Worksheets[language.Culture];
colCount = worksheet.Dimension.End.Column;
rowCount = worksheet.Dimension.End.Row;
//write data
}
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
xlPackage.Save();
And it is working great.
Now I want to retrieve the column names of each sheet in the excel using LinqToExcel and this is my code
string sheetName = language.Culture;
var excelFile = new ExcelQueryFactory(excelPath);
IQueryable<Row> excelSheetValues = from workingSheet in excelFile.Worksheet(sheetName) select workingSheet;
string[] headerRow = excelFile.GetColumnNames(sheetName).ToArray();
At header row it is throwing me an exception
An OleDbException exception was caught
External table is not in the expected format.
But I don't want to use Oledb and want to work with Linq To Excel.
Note: When I'm working with single sheet rather than multiple sheets
it is working fine and retrieving all columns. Where am I going wrong.
(Based on OP's Comments)
The AutoFitColumn function has always been a little touchy. The important thing to remember is to call it AFTER you load the cell data.
But if you want a use a minimum width (when columns are very narrow and you want to use a minimum) I find EPP to be unreliable. It seems to always use DefualtColWidth of the worksheet even if you pass in a minimumWidth to one of the function overloads.
Here is how I get around it:
[TestMethod]
public void Autofit_Column_Range_Test()
{
//http://stackoverflow.com/questions/31165959/how-to-retrieve-column-names-from-a-excel-sheet
//Throw in some data
var datatable = new DataTable("tblData");
datatable.Columns.Add(new DataColumn("Nar", typeof(int))); //This would not be autofitted without the workaround since the default width of a new ws, usually 8.43
datatable.Columns.Add(new DataColumn("Wide Column", typeof(int)));
datatable.Columns.Add(new DataColumn("Really Wide Column", typeof(int)));
for (var i = 0; i < 20; i++)
{
var row = datatable.NewRow();
row[0] = i;
row[1] = i * 10;
row[2] = i * 100;
datatable.Rows.Add(row);
}
var existingFile2 = new FileInfo(#"c:\temp\temp.xlsx");
if (existingFile2.Exists)
existingFile2.Delete();
using (var package = new ExcelPackage(existingFile2))
{
//Add the data
var ws = package.Workbook.Worksheets.Add("Sheet1");
ws.Cells.LoadFromDataTable(datatable, true);
//Keep track of the original default of 8.43 (excel default unless the user has changed it in their local Excel install)
var orginaldefault = ws.DefaultColWidth;
ws.DefaultColWidth = 15;
//Even if you pass in a miniumWidth as the first parameter like '.AutoFitColumns(15)' EPPlus usually ignores it and goes with DefaultColWidth
ws.Cells[ws.Dimension.Address].AutoFitColumns();
//Set it back to what it was so it respects the user's local setting
ws.DefaultColWidth = orginaldefault;
package.Save();
}
}

Windows azure - the specified table not found

I'm trying to get the daa from windows azure storage but I'm getting table not found. I've already saw the others answers but nothing works...
I did try this:
private void popula()
{
var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Conn"));
account.CreateCloudTableClient().CreateTableIfNotExist("fiscal");
var context = new CRUDManifestacoesEntities(account.TableEndpoint.ToString(), account.Credentials);
Hashtable ht = (Hashtable)ViewState["filtro"];
var teste = ViewState["x"].ToString();
if (ht == null)
GridView1.DataSource = context.SelectConc(teste);
else
GridView1.DataSource = context.SelectConc(ht);
}
public List<ManifestacaoGrid> SelectConc(string conc)
{
conc = Crypto.DecryptString(conc);
IQueryable<ManifestacaoEntity> results = null;
if (!conc.Equals("dfg"))
results = from c in ManifestacaoEntities where c.concessionaria == conc select c;
else
results = from c in ManifestacaoEntities select c;
var query = results.AsTableServiceQuery<ManifestacaoEntity>();
var queryResults = query.Execute();
List<ManifestacaoGrid> al = new List<ManifestacaoGrid>();
foreach (ManifestacaoEntity mf in queryResults)
{
.......
}
I'm getting this error:
TableNotFoundThe table specified does not exist.
RequestId:285f6ef7-b1ce-4c21-9406-3e9f6a58755b
Time:2014-01-15T14:30:55.7989535Z
EDIT: I did print '_account' to see if the credentials are correct:
var credencial = "Connection string with sensitive data: " + account.ToString(true);
and the AccountName and AccountKey are correct ...but how can I know if the requested table is correct?
The secundary key is needed in storage account?
I did found the problem. I write
public IQueryable<UserEntity> UserEntities
{
get
{
return this.CreateQuery<UserEntity>("tableName");
}
}
Instead of:
public IQueryable<UserEntity> UserEntities
{
get
{
return this.CreateQuery<UserEntity>("UserEntities");
}
}

Master details batch crud with entity framework only saving single detail record

I'm building a master details page with batch editing, that is multiple details records with single master record. but only one detail record is being saved into the data base. I tried to debug & found that detail loop is executing multiple time accurately but not the saving multiple data. Here is my Code for save method:
public ActionResult CMN_VAL_FORM(HRM_CMN_VLU_MST_ViewModel model)
{
//var ctx=new Entities1();
var CMN_VLU_MST_OBJ = new HRM_CMN_VLU_MST();
var CMN_VLU_DTL_OBJ = new HRM_CMN_VLU_DTL();
//using (TransactionScope transaction = new TransactionScope())
//{
using (var ctx = new Entities1())
{
var type_code = ctx.ExecuteStoreQuery<string>("select get_pk_code('hrm_cmn_vlu_mst','CMN_VLU_TYPE_CODE') from dual").SingleOrDefault(); //A scalar function to generate the code in the format yymmdd0001
var value_code = ctx.ExecuteStoreQuery<string>("select get_pk_code('hrm_cmn_vlu_dtl','CMN_VLU_CODE') from dual").SingleOrDefault();
CMN_VLU_MST_OBJ.CMN_VLU_TYPE_CODE = type_code;
CMN_VLU_MST_OBJ.CMN_VLU_REM = model.CMN_VLU_REM;
CMN_VLU_MST_OBJ.CMN_VLU_TYPE_FOR = model.CMN_VLU_TYPE_FOR;
CMN_VLU_MST_OBJ.CMN_VLU_TYPE_SRTNM = model.CMN_VLU_TYPE_SRTNM;
CMN_VLU_MST_OBJ.ENTRY_DATE = DateTime.Now;
CMN_VLU_MST_OBJ.CMN_VLU_TYPE_NAME = model.CMN_VLU_TYPE_NAME;
foreach (var item in model.HRM_CMN_VLU_DTL)
{
CMN_VLU_DTL_OBJ.CMN_VLU_LEVL = item.CMN_VAL_LEVL;
CMN_VLU_DTL_OBJ.CMN_VLU_REM = item.CMN_VLU_REM;
CMN_VLU_DTL_OBJ.CMN_VLU_SLNO = item.CMN_VLU_SLNO;
CMN_VLU_DTL_OBJ.CMN_VLU_TITL = item.CMN_VAL_TITL;
CMN_VLU_DTL_OBJ.CMN_VLU_CNTN = item.CMN_VAL_CNTN;
CMN_VLU_DTL_OBJ.CMN_VLU_CODE = value_code;
CMN_VLU_DTL_OBJ.CMN_VLU_TYPE_CODE = type_code;
CMN_VLU_DTL_OBJ.ENTRY_DATE = DateTime.Now;
CMN_VLU_DTL_OBJ.MAIL_ADDR_INT = item.MAIL_ADDR_INT;
CMN_VLU_DTL_OBJ.MAIL_ADDR_EXT = item.MAIL_ADDR_EXT;
CMN_VLU_DTL_OBJ.MAIL_AUTO_SEND_INT = item.MAIL_AUTO_SEND_INT;
CMN_VLU_DTL_OBJ.MAIL_AUTO_SEND_EXT = item.MAIL_AUTO_SEND_EXT;
CMN_VLU_DTL_OBJ.ACTIVE_STATUS = item.ACTIVE_STATUS;
CMN_VLU_MST_OBJ.HRM_CMN_VLU_DTL.Add(CMN_VLU_DTL_OBJ);
ctx.SaveChanges();
var temp_value_code = Int32.Parse(value_code);
temp_value_code++;
value_code = temp_value_code.ToString();
ctx.HRM_CMN_VLU_MST.AddObject(CMN_VLU_MST_OBJ);
}
ctx.SaveChanges();
// transaction.Complete();
//}
}
return View();
}
No Error message for the code, but not saving multiple detail records. What I'm doing wrong?
What I was doing wrong, I created the object just once & updated that same object every time while executing the foreach loop! I just moved the object declaration into the foreach loop & it works like a charm!

Error trying to loop through Linq query results

I need to pull any amount of records that correspond to a specific value (CourseCode), and insert these records into another table. This code works fine as long as the Linq code returns only one record, however if there is any more than that I get the following message:
An object with the same key already exists in the ObjectStateManager.
The existing object is in the Modified state. An object can only be
added to the ObjectStateManager again if it is in the added.
Below is my code:
if (_db == null) _db = new AgentResourcesEntities();
var prodCodes = from records in _db.CourseToProduct
where records.CourseCode == course.CourseCode
select records;
foreach (var pt in prodCodes.ToList())
{
agentProdTraining.SymNumber = symNumber;
agentProdTraining.CourseCode = course.CourseCode;
agentProdTraining.ProductCode = pt.ProductCode;
agentProdTraining.DateTaken = course.DateTaken;
agentProdTraining.Method = course.Method;
agentProdTraining.LastChangeOperator = requestor;
agentProdTraining.LastChangeDate = DateTime.Now;
agentProdTraining.DateExpired = course.ExpirationDate;
agentProdTraining.ProductCode = pt.ProductCode;
agentProdTraining.NoteId = pt.NoteId;
_db.AgentProductTraining.AddObject(agentProdTraining);
_db.SaveChanges();
PtAdded++;
EventLog.WriteEntry(sSource, "Product Training added", EventLogEntryType.Warning);
}
The loop is re-adding the same agentProdTraining object even though property values are changed. Create a new instance for each loop execution.
foreach (var pt in prodCodes.ToList())
{
var agentProdTraining = new AgentProductTraining();
agentProdTraining.SymNumber = symNumber;
agentProdTraining.CourseCode = course.CourseCode;
agentProdTraining.ProductCode = pt.ProductCode;
agentProdTraining.DateTaken = course.DateTaken;
agentProdTraining.Method = course.Method;
agentProdTraining.LastChangeOperator = requestor;
agentProdTraining.LastChangeDate = DateTime.Now;
agentProdTraining.DateExpired = course.ExpirationDate;
agentProdTraining.ProductCode = pt.ProductCode;
agentProdTraining.NoteId = pt.NoteId;
_db.AgentProductTraining.AddObject(agentProdTraining);
_db.SaveChanges();
PtAdded++;
EventLog.WriteEntry(sSource, "Product Training added", EventLogEntryType.Warning);
}

Update using LINQ to SQL

How can I update a record against specific id in LINQ to SQL?
LINQ is a query tool (Q = Query) - so there is no magic LINQ way to update just the single row, except through the (object-oriented) data-context (in the case of LINQ-to-SQL). To update data, you need to fetch it out, update the record, and submit the changes:
using(var ctx = new FooContext()) {
var obj = ctx.Bars.Single(x=>x.Id == id);
obj.SomeProp = 123;
ctx.SubmitChanges();
}
Or write an SP that does the same in TSQL, and expose the SP through the data-context:
using(var ctx = new FooContext()) {
ctx.UpdateBar(id, 123);
}
In the absence of more detailed info:
using(var dbContext = new dbDataContext())
{
var data = dbContext.SomeTable.SingleOrDefault(row => row.id == requiredId);
if(data != null)
{
data.SomeField = newValue;
}
dbContext.SubmitChanges();
}
AdventureWorksDataContext db = new AdventureWorksDataContext();
db.Log = Console.Out;
// Get hte first customer record
Customer c = from cust in db.Customers select cust where id = 5;
Console.WriteLine(c.CustomerType);
c.CustomerType = 'I';
db.SubmitChanges(); // Save the changes away
DataClassesDataContext dc = new DataClassesDataContext();
FamilyDetail fd = dc.FamilyDetails.Single(p => p.UserId == 1);
fd.FatherName=txtFatherName.Text;
fd.FatherMobile=txtMobile.Text;
fd.FatherOccupation=txtFatherOccu.Text;
fd.MotherName=txtMotherName.Text;
fd.MotherOccupation=txtMotherOccu.Text;
fd.Phone=txtPhoneNo.Text;
fd.Address=txtAddress.Text;
fd.GuardianName=txtGardianName.Text;
dc.SubmitChanges();
I found a workaround a week ago. You can use direct commands with "ExecuteCommand":
MDataContext dc = new MDataContext();
var flag = (from f in dc.Flags
where f.Code == Code
select f).First();
_refresh = Convert.ToBoolean(flagRefresh.Value);
if (_refresh)
{
dc.ExecuteCommand("update Flags set value = 0 where code = {0}", Code);
}
In the ExecuteCommand statement, you can send the query directly, with the value for the specific record you want to update.
value = 0 --> 0 is the new value for the record;
code = {0} --> is the field where you will send the filter value;
Code --> is the new value for the field;
I hope this reference helps.

Resources