Problem with modifying an MSI database property - c#

I need to modify the UpgradeCode property of the Upgrade MSI table via C#.
This code works ok with other tables' properties, but throws an error when I'm trying to modify these.
using (var database = new Database(TEMPDATABASE, DatabaseOpenMode.Direct))
{
string upgradeCode = Guid.NewGuid().ToString("B").ToUpper();
database.Execute("Update `Upgrade` Set `Upgrade`.`UpgradeCode` = '{0}'", upgradeCode);
}
The error is:
Microsoft.Deployment.WindowsInstaller.InstallerException: 'Function failed during execution.'

I got curious and pillaged github.com - and it giveth the following: Full project - just download it as a whole.
The actual code was (some unicode line feed issues in the file on github.com, I have fixed them up here):
public static void UpdateUpgradeTable(this Database db, Guid upgradeCode)
{
using (View view = db.OpenView("SELECT * FROM `Upgrade`", new object[0]))
{
view.Execute();
using (Record record = view.Fetch())
{
record[1] = upgradeCode.ToString("B").ToUpperInvariant();
view.Replace(record);
}
db.Commit();
}
}
I took the above and made the following mock-up (very ugly, but it worked):
using (Database db = new Database(#"C:\Test.msi", DatabaseOpenMode.Direct))
{
using (View view = db.OpenView("SELECT * FROM `Upgrade`", new object[0]))
{
view.Execute();
using (Record record = view.Fetch())
{
record[1] = "{777888DD-1111-1111-1111-222222222222}";
record[2] = "";
record[3] = "4.0.1";
record[4] = "";
record[5] = "1";
record[6] = "";
record[7] = "WIX_UPGRADE_DETECTED";
view.Replace(record);
}
db.Commit();
using (Record record = view.Fetch())
{
record[1] = "{777888DD-1111-1111-1111-222222222222}";
record[2] = "";
record[3] = "";
record[4] = "4.0.1";
record[5] = "1";
record[6] = "";
record[7] = "WIX_DOWNGRADE_DETECTED";
view.Replace(record);
}
db.Commit();
}
}

The SDK doc says:
UPDATE queries only work on nonprimary key columns.
UpgradeCode is the primary key for the Upgrade table.

Related

Concurrency violation: the UpdateCommand affected 0 of the expected 1 records (Simple 1 row table with 4 columns in Windows forms)

I have a one-row table with some identity values for an installation. It has a primary key column (value=1) and three other columns.
On initial app startup I am updating the three columns with new values.
But then on update, I get the above error.
The data is not bound to form controls - it's all in the code below.
I've tried dropping the PK, but then I can't use the SQL builder.
I've added the PK column that never changes, rather than using the first data column as the PK.
I've also tried banging my head against a brick wall, but that didn't work either!
SQLiteConnection cnWLLocal = new SQLiteConnection();
cnWLData.ConnectionString = "Data Source=WordLightData.sqlite; Version = 3; DateTimeFormat=CurrentCulture ;";
string s = "Select Key, WLIdentity, WLIdentityCode, LastSongDBCheck from LocalInfo";
cmdLocalInfo = new SQLiteCommand(s, cnWLLocal);
daLocalInfo = new SQLiteDataAdapter(cmdLocalInfo);
dsLocalInfo = new DataSet();
daLocalInfo.Fill(dsLocalInfo, "LocalInfo"); // BTW this works perfectly - data is returned
bldLocalInfo = new SQLiteCommandBuilder(daLocalInfo);
dsLocalInfo.Tables["LocalInfo"].Rows[0]["WLIdentity"] = "New value";
dsLocalInfo.Tables["LocalInfo"].Rows[0]["WLIdentityCode"] = "New value";
dsLocalInfo.Tables["LocalInfo"].Rows[0]["LastSongDBCheck"] = Convert.ToInt32(DateTime.Now.ToString("yyyyMMdd"));
DataSet dsChanges = new DataSet();
dsChanges = dsLocalInfo.GetChanges(DataRowState.Modified);
if (dsChanges != null)
{
daLocalInfo.UpdateCommand = bldLocalInfo.GetUpdateCommand();
int iRowsUpdated = daLocalInfo.Update(dsChanges, “LocalInfo”);
}
The table is defined in SQLite as:
Key - Integer PK
WLIdentity - String (20)
WLIdentityCode - Text (15)
LastSongDBCheck - Integer (8)
Can you try this code :
var cnWLLocal = new SQLiteConnection
{
ConnectionString = "Data Source=WordLightData.sqlite; Version = 3; DateTimeFormat=CurrentCulture ;"
};
const string s = "Select Key, WLIdentity, WLIdentityCode, LastSongDBCheck from LocalInfo";
using (var cmdLocalInfo = new SQLiteCommand(s, cnWLLocal))
{
using (var daLocalInfo = new SQLiteDataAdapter(cmdLocalInfo))
{
using (var dsLocalInfo = new DataSet())
{
daLocalInfo.Fill(dsLocalInfo, "LocalInfo"); // BTW this works perfectly - data is returned
using (var bldLocalInfo = new SQLiteCommandBuilder(daLocalInfo))
{
dsLocalInfo.Tables["LocalInfo"].Rows[0]["WLIdentity"] = "New value";
dsLocalInfo.Tables["LocalInfo"].Rows[0]["WLIdentityCode"] = "New value";
dsLocalInfo.Tables["LocalInfo"].Rows[0]["LastSongDBCheck"] = Convert.ToInt32(DateTime.Now.ToString("yyyyMMdd"));
using (DataTable tableChanges = dsLocalInfo.Tables["LocalInfo"].GetChanges(DataRowState.Modified))
{
if (tableChanges != null)
{
daLocalInfo.UpdateCommand = bldLocalInfo.GetUpdateCommand();
int iRowsUpdated = daLocalInfo.Update(tableChanges);
}
}
}
}
}
}

Insert into database using Entity Framework from C#

I am trying to insert a text file formatted in C Sharp to a Microsoft SQL server. I have 2 tables Transaction and TMatch in which I want to populate the data. 4 attributes each. I have created 2 classes for each. I am aware of how to input data manually into the database through the .Add() and .SaveChanges().
Here is what I have so far:
//Database insertions
TTransaction txn = new TTransaction();
**txn.Amount = 56; //I want a variable used below (AMOUNT) to go into amount.
txn.TRN = "sdfgsdfg";** //(TxnNo) to go into TRN
ScotiaNYAEntities context = new ScotiaNYAEntities();
context.TTransactions.Add(txn);
context.SaveChanges();
Traversing the text file using a while loop.
{
if (line.Contains("AMOUNT:")) //Look where to end for Transaction Text
{
// For Amount
IsAmount=true;
if(IsAmount)
{
Amount = line.Replace("AMOUNT:", String.Empty).Trim();
Console.WriteLine("AMOUNT: ********");
Console.WriteLine(Amount);
}
}..............................................
I am not sure how to reference a variable instead of just values.
Thank you.
leap of faith but you could have something like this
using (ScotiaNYAEntities context = new ScotiaNYAEntities())
{
foreach (string line in File.ReadLines(pathToFile))
{
if (line.Contains("AMOUNT:"))
{
if (IsAmount)
{
string amount = line.Replace("AMOUNT:", string.Empty).Trim();
TTransaction txn = new TTransaction();
txn.Amount = amount;
txn.TRN = "sdfgsdfg";
context.TTransactions.Add(txn);
}
}
}
context.SaveChanges();
}
This is what I did:
In the for loop for reading the file line by line
String TxnLOC = null;
IsTransactionLocation= false;
if (line.Contains("TRANSACTION LOC:"))
{
IsTransactionLocation = true;
if (IsTransactionLocation)
{
TxnLOC = line.Replace("TRANSACTION LOC:", String.Empty).Trim();
Console.WriteLine("The Transaction Location: ********");
Console.WriteLine(TxnLOC);
//Database insertion fot TTransaction Table
TTransaction txn = new TTransaction();
txn.TRN = txnNo;
txn.Amount = Convert.ToDecimal(Amount);
txn.TransactionLocation = TxnLOC;
context.TTransaction.Add(txn); //Adding to the database
context.SaveChanges();
IsTxnSection = false;//For 1 to many relationship
}
}

C# - NullReferenceException while moving data from Excel to SQL Server

I am developing a web application in which i have to import the data in SQL Server from given Excel files using C# and ASP.NET MVC. For this purpose I followed this article. So I used ExcelDataReader to read the Excel files. Furthermore I have used SqlBulkCopy in my code to insert the data into the database. following is my code:
The Create method
var bData = getBillData();
var connString = ConfigurationManager.ConnectionStrings["WASABill"].ConnectionString;
DataTable table = new DataTable();
using (var reader = ObjectReader.Create(bData))
{
table.Load(reader);
}
using (SqlBulkCopy bcp = new SqlBulkCopy(connString))
{
bcp.ColumnMappings.Add("AccountNo", "AccountNo");
bcp.ColumnMappings.Add("BillNo", "BillNo");
bcp.ColumnMappings.Add("Category", "Category");
bcp.ColumnMappings.Add("Billing_Period", "Billing_Period");
bcp.ColumnMappings.Add("Name", "Name");
bcp.ColumnMappings.Add("Address", "Address");
bcp.ColumnMappings.Add("Issue_Date", "Issue_Date");
bcp.ColumnMappings.Add("Due_Date", "Due_Date");
bcp.ColumnMappings.Add("Water_Bill", "Water_Bill");
bcp.ColumnMappings.Add("Sewerage_Bill", "Sewerage_Bill");
bcp.ColumnMappings.Add("Aquifer_Charges", "Aquifer_Charges");
bcp.ColumnMappings.Add("Current_Amount", "Current_Amount");
bcp.ColumnMappings.Add("Arrears", "Arrears");
bcp.ColumnMappings.Add("Service_Charges", "Service_Charges");
bcp.ColumnMappings.Add("Payable_within_DueDate", "Payable_within_DueDate");
bcp.ColumnMappings.Add("Surcharge", "Surcharge");
bcp.ColumnMappings.Add("Payable_after_DueDate", "Payable_after_DueDate");
bcp.ColumnMappings.Add("Payment_History_1", "Payment_History_1");
bcp.ColumnMappings.Add("Paid_1", "Paid_1");
bcp.ColumnMappings.Add("Payment_History_2", "Payment_History_2");
bcp.ColumnMappings.Add("Paid_2", "Paid_2");
bcp.ColumnMappings.Add("Payment_History_3", "Payment_History_3");
bcp.ColumnMappings.Add("Paid_3", "Paid_3");
bcp.ColumnMappings.Add("Area", "Area");
bcp.ColumnMappings.Add("Water_Rate", "Water_Rate");
bcp.ColumnMappings.Add("Sewerage_Rate", "Sewerage_Rate");
bcp.ColumnMappings.Add("Discharge_Basis", "Discharge_Basis");
bcp.ColumnMappings.Add("Pump_Size", "Pump_Size");
bcp.ColumnMappings.Add("Ferrule_Size", "Ferrule_Size");
bcp.ColumnMappings.Add("Meter_Type", "Meter_Type");
bcp.ColumnMappings.Add("Meter_Status", "Meter_Status");
bcp.ColumnMappings.Add("Last_Readin", "Last_Readin");
bcp.ColumnMappings.Add("Current_Reading", "Current_Reading");
bcp.ColumnMappings.Add("Water_Aquiffer_Charges", "Water_Aquiffer_Charges");
bcp.DestinationTableName = "WASA_Bill_Detail";
bcp.WriteToServer(table);
}
var rowCount = table.Rows.Count; //Number of rows in data table
//if (ModelState.IsValid)
//{
// db.WASA_Bill_Detail.Add(wASA_Bill_Detail);
// db.SaveChanges();
// return RedirectToAction("Index");
//}
TempData["RowCount"] = rowCount;
return RedirectToAction("Index");
The method which reads the Excel file and returns the data as a list
public IEnumerable<WASA_Bill_Detail> getBillData()
{
List<WASA_Bill_Detail> billDetaileList = new List<WASA_Bill_Detail>();
//string path = #TempData["FilePath"].ToString();//#"E:\W317.xlsx";
string path = TempData["FilePath"].ToString();
string excelpath = Server.MapPath(path);
if(path!=null)
{
var excelData = new ExcelData(excelpath);
var billRecords = excelData.getData("Sheet1");
foreach (var row in billRecords)
{
var billDetail = new WASA_Bill_Detail()
{
AccountNo = row["ACCOUNT#"].ToString(),
BillNo = row["BILLNO"].ToString(),
Category = row["CATEGORY"].ToString(),
Billing_Period = row["BILLING_PERIOD"].ToString(),
Name = row["NAME"].ToString(),
Address = row["ADDRESS"].ToString(),
Issue_Date = row["ISSUE_DATE"].ToString(),
Due_Date = row["DUE_DATE"].ToString(),
Water_Bill = row["WATER_BILL"].ToString(),
Sewerage_Bill = row["SEWERAGE BILL"].ToString(),
Aquifer_Charges = row["AQUIFER"].ToString(),
Current_Amount = row["CURRENT AMOUNT"].ToString(),
Arrears = row["ARREARS"].ToString(),
Service_Charges = row["SERVICE CHARGES"].ToString(),
Payable_within_DueDate = row["PAYABLE WITHIN DUEDATE"].ToString(),
Surcharge = row["SURCHARGE"].ToString(),
Payable_after_DueDate = row["AFTER DUE DATE"].ToString(),
Payment_History_1 = row["PAY HISTORY 1"].ToString(),
Paid_1 = row["PAID 1"].ToString(),
Payment_History_2 = row["PAY HISOTRY 2"].ToString(),
Paid_2 = row["PAID 2"].ToString(),
Payment_History_3 = row["PAY HISOTRY 3"].ToString(),
Paid_3 = row["PAID 3"].ToString(),
Area = row["AREA"].ToString(),
Water_Rate = row["WATER RATE"].ToString(),
Sewerage_Rate = row["SEWER RATE"].ToString(),
Discharge_Basis = row["DISCHAGE"].ToString(),
Pump_Size = row["PUMP SIZE"].ToString(),
Ferrule_Size = row["FERRULE SIZE"].ToString(),
Meter_Type = row["METER TYPE"].ToString(),
Meter_Status = row["METER STATUS"].ToString(),
Last_Readin = row["LAST READING"].ToString(),
Current_Reading = row["CURRENT READING"].ToString(),
Water_Aquiffer_Charges = row["AQUIFER CHARGES"].ToString(),
};
billDetaileList.Add(billDetail);
}
}
return billDetaileList;
}
Everything is working fine on my development machine. File uploaded properly and then inserted into the database using bcp.
But when I publish this to the hosting server the NullReferenceException occurred at
WASAWeb.Controllers.AdminControllers.WASA_Bill_DetailController.getBillData() +128
I could not understand as it is working 100% fine in my development machine. I have checked that file is properly uploaded to the server.
Any help with this?
you can use this:
private string GetStringValue(object obj)
{
string str = null;
if(obj != null)
str = obj.ToString().Trim();
return str;
}
call
......
AccountNo = GetStringValue(row["ACCOUNT#"])
......

Linked Table Shows As read only

I am using C# to create a SQL Server view, then open an access database and link the table into access. The create view statement, open database statement and link statement work great BUT the catch here is it will always link the table as read-only. What piece o'code do I need to add or update current so that the view is not always linked as read-only?
string MasterDatabase = "R:\\Testing\\MasterDatabase.mdb";
DAO.Database dd;
DAO.DBEngine db = new DAO.DBEngine();
DAO.TableDef tdf9;
bool found = false;
DAO.TableDef tdf1;
string Table = "ServiceEntranceLog";
string TableAccess = "Service_Entrance_Log";
using (var connection = new SqlConnection(ConnectionStringHere))
using (var command = connection.CreateCommand())
{
using (var command4 = connection.CreateCommand())
{
command4.CommandText = "CREATE VIEW HelperView" AS SELECT * FROM monster.ServiceEntranceLog";
command4.ExecuteNonQuery();
}
}
if (_combobox1.SelectedItems.Contains("MasterDatabase"))
{
dd = db.OpenDatabase(CRDB);
try
{
string[] tableNames = new string[1] { TableAccess };
for (int q = tableNames.GetLowerBound(0); q <= tableNames.GetUpperBound(0); q++)
{
foreach (DAO.TableDef tabledef in dd.TableDefs)
{
string name = tableNames[q];
if (tabledef.Name == name) { found = true; }
try { if (found) { dd.TableDefs.Delete(name); } }
catch { }
}
}
}
catch { }
tdf1 = dd.CreateTableDef(TableAccess);
tdf1.Connect = connectionString;
tdf1.SourceTableName = Table;
dd.TableDefs.Append(tdf1);
}
Alritey, so it seems the issue is I needed to define a primary key when linking in the table into access so that the table would be updateable. Using this syntax does the trick
dd.Execute "CREATE UNIQUE INDEX SomeIndex ON SomeTable (PrimaryKeyColumn) WITH PRIMARY"

Insert data into database using LINQ

I wrote a very simple method. It saves data from class DayWeather to the database. Method checks if line with that day exist in table and update her or create a new line.
I am doing it by adding new class for LINQ and move table from Server Inspector to the constructor. It generate new class WeatherTBL.
Method itself looks like this:
public static void SaveDayWeather(DayWeather day)
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
var existingDay =
(from d in db.WeatherTBL
where d.DateTime.ToString() == day.Date.ToString()
select d).SingleOrDefault<WeatherTBL>();
if (existingDay != null)
{
existingDay.Temp = day.Temp;
existingDay.WindSpeed = day.WindSpeed;
existingDay.Pressure = day.Pressure;
existingDay.Humidity = day.Humidity;
existingDay.Cloudiness = day.Cloudiness;
existingDay.TypeRecip = day.TypeRecip;
db.SubmitChanges();
}
else
{
WeatherTBL newDay = new WeatherTBL();
newDay.DateTime = day.Date;
newDay.Temp = day.Temp;
newDay.WindSpeed = day.WindSpeed;
newDay.Pressure = day.Pressure;
newDay.Humidity = day.Humidity;
newDay.Cloudiness = day.Cloudiness;
newDay.TypeRecip = day.TypeRecip;
db.WeatherTBL.InsertOnSubmit(newDay);
db.SubmitChanges();
}
}
}
When I tried to call him from UnitTest project:
[TestMethod]
public void TestDataAccess()
{
DayWeather day = new DayWeather(DateTime.Now);
DataAccessClass.SaveDayWeather(day);
}
It write, that test has passed successfully. But if look into table, it has`t chanched.
No error messages shows. Does anyone know whats the problem?
P.S. Sorry for my bad English.
UDP
Problem was in that:
"...db maybe copied to the debug or release folder at every build, overwriting your modified one". Thanks #Silvermind
I wrote simple method to save employee details into Database.
private void AddNewEmployee()
{
using (DataContext objDataContext = new DataContext())
{
Employee objEmp = new Employee();
// fields to be insert
objEmp.EmployeeName = "John";
objEmp.EmployeeAge = 21;
objEmp.EmployeeDesc = "Designer";
objEmp.EmployeeAddress = "Northampton";
objDataContext.Employees.InsertOnSubmit(objEmp);
// executes the commands to implement the changes to the database
objDataContext.SubmitChanges();
}
}
Please try with lambda expression. In your code, var existingDay is of type IQueryable
In order to insert or update, you need a variable var existingDay of WeatherTBL type.
Hence try using below..
var existingDay =
db.WeatherTBL.SingleOrDefault(d => d.DateTime.Equals(day.Date.ToString()));
if(existingDay != null)
{
//so on...
}
Hope it should work..
Linq to SQL
Detail tc = new Detail();
tc.Name = txtName.Text;
tc.Contact = "92"+txtMobile.Text;
tc.Segment = txtSegment.Text;
var datetime = DateTime.Now;
tc.Datetime = datetime;
tc.RaisedBy = Global.Username;
dc.Details.InsertOnSubmit(tc);
try
{
dc.SubmitChanges();
MessageBox.Show("Record inserted successfully!");
txtName.Text = "";
txtSegment.Text = "";
txtMobile.Text = "";
}
catch (Exception ex)
{
MessageBox.Show("Record inserted Failed!");
}

Categories