How to declare a variable to hold the results of a db.query.
I'm using Webpages and Webmatrix to build some small apps.
As part of the authentication process I have to perform slightly different queries on the database depending on who is logged in.
var db = Database.Open("DBName");
var mySQL = "";
// WHAT LEVEL IS THE USER
if (PageData["editorLevel"] < 11){
//set the sql
//perform the db.Query
}else if (PageData["editorLevel"]<51){
//set the sql
//perform the db.Query
}else if (PageData["editorLevel"] < 101){
//set the sql
//perform the db.Query
}
The db.Query will contain differing parameters so has to be executed within the if else block.
If I do it like so;
var myResults = db.Query(mySQL, parameter list)
then myResults will not be available in the rest of the page, so I need to define myResults first. I have tried all sorts of variations of Type myResults and var myResults but gettign no where.
Thanks
The Database helper Query method returns an IEnumerable<dynamic>, so this could be your code:
var db = Database.Open("DBName");
var mySQL = "";
IEnumerable<dynamic> myResults = null;
// WHAT LEVEL IS THE USER
if (PageData["editorLevel"] < 11){
//set the sql
myResults = db.Query(mySQL, parameter list);
}
Related
I use a SQLite database to populate a listview with a generic list of TodoItems:
ListView.ItemsSource = await App.Database.GetItemsAsync("SELECT * FROM [TodoItem]");
I can read data of the same kind from a database source using the HttpClient class as well via
public async Task<List<TodoItem>> ReadDataAsync ()
....
Items = new List<TodoItem> ();
....
var content = await response.Content.ReadAsStringAsync ();
Items = JsonConvert.DeserializeObject <List<TodoItem>> (content);
....
return Items;
whereafter I can use this as a data source as well:
ListView.ItemsSource = await App.ReadDataAsync();
Both ways work well.
What I want now is combine both routines to accomplish a code which checks whether we have an online connection, if yes, drop the database and populate it using the result of ReadDataAsync from above, if no, leave the database alone.
I found no way to directly assign a List to my database, overwriting the whole contents, I think of something like:
App.Database.Items = await App.ReadDataAsync();
but SQLite doesn't seem to expose the data store directly. How can I accomplish this?
For android for example, you could try: There's no need to drop the database.
//Check for internet connection
var connectivityManager =
(ConnectivityManager)this.GetSystemService("connectivity");
var activeConnection = connectivityManager.ActiveNetworkInfo;
if ((activeConnection != null) && activeConnection.IsConnected)
{
//Make call to the API
var list = await App.ReadDataAsync();
//Update or Insert local records
foreach (var item in list)
{
var success = UpdateOrInsert(item);
//Do something after - like retry incase of failure
}
}
The UpdatedOrInsert method can look like:
private bool UpdateOrInsert(TodoItem item)
{
var rowsAffected = App.Database.Update(item);
if (rowsAffected == 0)
{
// The item doesn't exist in the database, therefore insert it
rowsAffected = App.Database.Insert(item);
}
var success = rowsAffected > 0;
return success;
}
I have the following query in LINQ as an example. Is it possible to save the results of the GetCalendarResources function so I wouldn't have to call it more than once? Thanks.
var query = from T in query2.AsEnumerable()
select new Event
{
resource = GetCalendarResources(T.eventID),
text = GetCalendarResources(T.eventID) + T.eventName
};
You can use the let keyword, which gives you the liberty to use its value for the next level:
var query = from T in query2.AsEnumerable()
let res= GetCalendarResources(T.eventID)
select new Event
{
resource =res,
text = res + T.eventName
};
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();
}
}
public static object ExecuteScalar(string SQL)
{
try
{
var A = new EGModel.EGEntity().Connection;
var command = ((EntityConnection)(A)).StoreConnection.CreateCommand();
command.CommandType = System.Data.CommandType.Text;
command.CommandText = SQL;
if (((EntityConnection)(A)).StoreConnection.State == System.Data.ConnectionState.Closed)
((EntityConnection)(A)).StoreConnection.Open();
return command.ExecuteScalar();
}
catch { return null; }
}
public object MFICHE(int ID)
{
var i = from b in IConnection.EGEntity().fiche
where (m.ID== ID)
select new { b.Date, m.Name, Addresss = IConnection.ExecuteScalar("SELECT main.F_ADDRESS(4588)") };
return i;
}
I am getting error:
LINQ to Entities does not recognize the method 'System.Object ExecuteScalar(System.String)' method, and this method cannot be translated into a store expression.
Why i am getting error?
But Addresss = "ASASAS" is runing?
The problem is that the expression tree generated from your query includes a call to your ExecuteScalar method - which the Entity Framework expression parser doesn't know anything about. It doesn't look inside that method to see what it's doing - it just knows that the call exists, and fails because it can't translate it.
You wouldn't normally want to execute a separate SQL statement for each result returned from a query? You've got an obvious "N+1 selects" problem.
If you know you've only got a single result (due to the ID constraint) you could fetch the relevant data into an object and then execute the second query:
public object MFICHE(int ID)
{
var query = from b in IConnection.EGEntity().fiche
where b.ID == ID
select new { b.Date, b.Name };
// You only expect a single result, right?
var result = query.Single();
// Shouldn't this be using something to do with the result?
var address = IConnection.ExecuteScalar("SELECT main.F_ADDRESS(4588)");
return new { result.Date, result.Name, Address = address };
}
As an aside, it's very odd to have static methods in a type beginning with I, which would usually be an interface. Additionally, this code:
catch { return null; }
is horrible - you should catch specific exceptions, log them, and normally rethrow them. It's almost never appropriate to just carry on as if nothing had gone wrong.
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.