i have a windows phone application and am trying to connect to a database. The database is valid, i have verified. I am using codeplex's sqlite client to try to connect.
First i add my database to my project using ">add>Existing item>" and after that i try to connect using the code :
db = new SQLiteConnection(#"Database.db");
db.Open();
Debug.WriteLine("DB opened");
SQLiteCommand cmd = db.CreateCommand("SELECT * FROM Tags");
var lst = cmd.ExecuteQuery<Tags>();
foreach (Tags r in lst)
{
Debug.WriteLine(r.Tag);
}
Debug.WriteLine(":D");
My Tags class looks like this :
public class Tags
{
public int id { get; set; }
public string Tag { get; set; }
}
And i get an error in the sqlite project ( in Sqlite3.Vdbe Prepare()) saying that there is no such table:Tags . The table is there, i've viewed the database and the name of the table is correct.
What am i doing wrong?
Try supplying the full path instead of just the file name. I believe windows phone does not have a "current directory" so the application probably looks in the root folder.
If you supply a file that does not exist to the SQLite client, it will silently create an empty database for you and "connect" to that.
i've found that my database must be in the IsolatedStorage. Here is a sample i found useful http://dotnetslackers.com/articles/silverlight/Windows-Phone-7-Native-Database-Programming-via-Sqlite-Client-for-Windows-Phone.aspx
Related
I'm having an issue using the Windows credential manager in a project. I am using it to replace the username and password on the connectionString in my appsettings, and in the development and QA environments everything works fine, but in the production environment (which I don't have complete access to) it does not. The issue is its returning empty string when I load the credentials from the target.
Here is where I am loading it:
public static CredentialModel GetCredential(string target)
{
CredentialModel credentialDto = new CredentialModel();
using var credential = new Credential
{
Target = target
};
credential.Load();
credentialDto.UserName = credential.Username;
credentialDto.Password = credential.Password;
return credentialDto;
}
And this is the CredentialModel
public class CredentialModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
And where I replace the credentials in the connectionString:
StringBuilder connectionString = new(host.Configuration.GetConnectionString("RemessasConnectionString"));
var credential = CredentialService.GetCredential("Pegasus");
connectionString.Replace("$userId", credential.UserName);
connectionString.Replace("$password", credential.Password);
ConnectionString = connectionString.ToString();
For debugging's sake I added a line to the log in order to see what was being added to the connectionString, and it is replacing it with an empty string in production, but the actual values in development.
I have one idea about the reason for this, the application is running with a windows user and that user does not have access to the windows credential manager in the production server (but I think this would return an error not just empty strings).
If anyone can point me in the right direction, or has any suggestions for me to try I am all ears.
As #richard-deeming pointed out, the its because the user running the application does not have access to the credentials stored since they were stored under a different account than the one running the service. Look at his comment for more detail.
THE GOAL
I'm trying to have a class library shared between an ASP.NET Core web app and other projects/solutions and the class should be able to interact with whatever database is being used by the calling process/environment.
THE PROBLEM
I have a class library that is throwing up a weird error when used in my ASP.NET Core 3.1 web app. The class library is actually shared between the front end (the website) and the backend app that takes care of some recurring, heavy load processes. I'm using EF Core with both front and back ends and the database is on Azure, not my local machine. Yet, when the web app tries to do some work I am getting the following error:
An attempt to attach an auto-named database for file C:...\bin\Debug\netcoreapp3.1\aspnetdb.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
This doesn't make sense to me at all since the DB is on Azure. Also, calling the same exact method in the library using the backend app doesn't throw up this error. The connection string is stored in appsettings.json for the website and app.config for the backend.
This is block of code that is throwing the error, but again this is only happening on the ASP.NET Core project on the SaveChanges() call:
public static void AddLogEvent(int Severity, DateTime EventTime, string EventType, string User, string Message)
{
DBEntities context = new DBEntities();
DbSet<LogEvent> dbSet = context.Set<LogEvent>();
LogEvent NewRecord = new LogEvent();
NewRecord.Id = Guid.NewGuid();
NewRecord.Severity = Severity;
NewRecord.EventTime = EventTime;
NewRecord.EventType = EventType;
NewRecord.User = User;
NewRecord.Message = Message;
dbSet.Add(NewRecord);
context.SaveChanges();
}
Within DBEntities, I am overriding the OnConfiguring() method to ensure proper connection for whatever environment is making the call as such:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
bool FoundValidConnection = false;
if (ConfigurationManager.ConnectionStrings.Count > 0)
{
foreach (ConnectionStringSettings connstr in ConfigurationManager.ConnectionStrings)
{
if (FoundValidConnection == false)
{
if (string.Compare(connstr.Name.Trim().ToUpper(), "DefaultConnection".ToUpper()) == 0)
{
optionsBuilder.UseSqlServer(connstr.ConnectionString);
FoundValidConnection = true;
break;
}
}
}
foreach (ConnectionStringSettings connstr in ConfigurationManager.ConnectionStrings)
{
if (FoundValidConnection == false)
{
if (string.Compare(connstr.Name.Trim().ToUpper(), "DBEntities".ToUpper()) == 0)
{
optionsBuilder.UseSqlServer(connstr.ConnectionString);
FoundValidConnection = true;
break;
}
}
}
if (FoundValidConnection == false)
{
//if still haven't found one of the expected connection string names, then take whatever the first one is.
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings[0].ConnectionString);
FoundValidConnection = true;
}
}
else
{
//nothing to do. there are no connection strings in the ConfigurationManager
}
}
}
Lastly, when I step through debugging on the website, I can see that the only connection string located in ConfigurationManager.ConnectionStrings is 1 with a name of LocalSqlServer and a connection string set to:
data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true
Which seems to be my local testing SQLExpress instance but is not used anywhere in the web app. All references or connection strings to the local testing database in SQLExpress have been removed so I am confused as to how this is showing up and the one in appsettings.json is being ignored. I also don't understand how optionsBuilder.IsConfigured is returning FALSE on the web app. I expected that context to already be configured.
I ended up changing the last if statement to the following:
if (FoundValidConnection == false)
{
try
{
//read from appsettings.json directly instead
string connString = new ConfigurationBuilder().SetBasePath(System.IO.Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build().GetSection("ConnectionStrings").GetSection("DefaultConnection").Value;
optionsBuilder.UseSqlServer(connString);
FoundValidConnection = true;
}
catch (System.Exception ex)
{
}
}
As Ivan noted in the comments above, ConfigurationManager from System.Configuration only works with app.config, which is XML based. ASP.NET Core utilizes appsettings.json which is, obviously, JSON based. So the solution was to modify the last check to be such that if the app.config checks fail and produce nothing then we assume the code is being called by something using appsettings.json and that one line uses ConfigurationBuilder to get the app's directory, build the configuration based on that file and get the expected connection by it's section and name.
References to Microsoft.Extensions.Configuration.FileExtensions and Microsoft.Extensions.Configuration.Json were required for SetBasePath() and AddJsonFile(), respectively.
The try/catch block is needed in the event there is some unforeseen error and the appsettings/json doesn't contain the expected section/name. Although, an error would eventually get thrown up somewhere when trying to interact with the database if nothing was set.
I'm using Linq to Excel library for reading excel tables. Until now, it was working good locally, the method ExcelQueryFactory gets the route of the excel by this way:
var book = new ExcelQueryFactory(#"C:\data.xls");
Now, I would like to use it online on a Rest Api, the POST used for uploading the Excel to the web api is the following:
[HttpPost]
[Route("Upload")]
public Task<HttpResponseMessage> UploadFile() {
List<string> savedFilePath = new List<string>();
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string rootPath = HttpContext.Current.Server.MapPath("~/UploadedFiles");
var provider = new MultipartFileStreamProvider(rootPath);
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsCanceled || t.IsFaulted)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
foreach (MultipartFileData item in provider.FileData)
{
try
{
string name = item.Headers.ContentDisposition.FileName.Replace("\"", "");
string newFileName = Guid.NewGuid() + Path.GetExtension(name);
Debug.WriteLine(item.LocalFileName);
File.Move(item.LocalFileName, Path.Combine(rootPath, newFileName));
Uri baseuri = new Uri(Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.PathAndQuery, string.Empty));
//RELATIVE PATH
string fileRelativePath = "~/UploadedFiles/" + newFileName;
//LeerExcel(fileRelativePath);
//ABSOLUTE PATH
Uri fileFullPath = new Uri(baseuri, VirtualPathUtility.ToAbsolute(fileRelativePath));
savedFilePath.Add(fileFullPath.ToString());
//LeerExcel(savedFilePath[0]);
}
catch (Exception ex)
{
string message = ex.Message;
}
}
// string rutaFin = "~" + savedFilePath[0];
// string rest = rutaFin.Replace("http://localhost:56618", "");
// LeerExcel(rest);
return Request.CreateResponse(HttpStatusCode.Created, savedFilePath);
});
return task;
}
So, by choosing the excel manually, neither the absolute path or relative path on the server work for the ExcelQueryFactory string route.
The routes get by this method are the following:
ABSOLUTE:
http://localhost:56618/UploadedFiles/9a27e785-e486-4807-8a80-7abb9b940d8b.xls
And the relative:
/UploadedFiles/9a27e785-e486-4807-8a80-7abb9b940d8b.xls
Is possible to use by the way I want to? During the server is online, the obtained absolute path is accesible, so if I access to that URL, the file is downloaded.
the problem is solved:
As I said, I thought only this library worked locally, but it wasn't.
Since Microsoft has launched a new big update, many people have notice some problems when using Database engine, “Unexpected error from external database driver (1). (Microsoft JET Database Engine)” after applying October security updates.
First, I created a Fake.txt file on /UploadedFiles, folder that is located on the project repository and I give it permission to be always copied, as follows:
Fake.txt properties
With this file, I´m achieving that UploadedFiles folder is copied every time I run the server.
Next step:
Due to Microsoft big update, the recomendation is to "download and install the Microsoft Access Database Engine 2010 Redistributable, and then modify the DB connection strings in Microsoft Excel to use ACE as a provider. Example: Change Provider=Microsoft.Jet.OLEDB.4.0 to Provider=Microsoft.ACE.OLEDB.12.0."
I only have downloaded and install that file, but during this day, 3 new windows updates were installed, so, I dont know if this 3 updates are related with the solution of this problem.
The updates are:
Update 1
Update 2
Update 3
After installing the 2010 database engine version file, I changed the excel extension from .xls to .xlsx and now all work.
This is my first post, but I have been scouring the stack for how I might use a text file or a SQLite database in Xamarin for Visual Studio. All the examples I have found end up in java, or in the old Mono android code.
The jist of the application is to read GPS data, display it, and save the latitude and longitude along with some identifying info such as room number. I have the display portion of the app working nicely, so now I need to find a way to save the information, so that the data can be passed along to a future class to finish creating a campus navigation app.
Here are some of the related portions:
path = GetDir("MCCMapping/",FileCreationMode.Append).ToString();
I am not sure this is correct to set the directory for the file creation.
String location = String.Format("{0}|{1}|{2}|{3}", roomNum.Text, campus.SelectedItem.ToString(), current.Latitude.ToString(),
current.Longitude.ToString());
using (data_file = new StreamWriter(path+"/MCC_ROOM_DATA.txt", true))
{
data_file.WriteLine(location);
}
This is not quite working. I need to be able to access the .txt file from outside the application, or even implement a SQLite database to store the same information. I have all the necessary manifest permissions. My device does not have external storage, so it will emulate it if that is the route that must be taken.
Anything you might have to help me along would be appreciated. Thanks.
Update 1:
folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
conn = new SQLiteAsyncConnection(System.IO.Path.Combine(folder, "MCC_ROOMS.db"));
conn.CreateTableAsync<Room>().ContinueWith(t => {});
and this
public class Room
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Campus { get; set; }
[Unique]
public string Room_Num { get; set; }
[Unique]
public decimal Room_Latitude { get; set; }
[Unique]
public decimal Room_Longitude { get; set; }
}
I am not quite sure what to put in the continue with portion. Also, would this allow me to access the table from a different application later? Thanks.
Update 2: Thanks to Jason, I have a working application. I used the external storage directory that is built in, and can then access the file if I turn usb debugging off.
Xamarin provides enumerations that help you get the folder paths of the folders that you are allowed to access. You cannot just write to arbitrary file paths.
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var filename = Path.Combine(path, "mydata.txt");
Once you have the path, you can use normal file IO operations to read and write.
using (data_file = new StreamWriter(filename, true))
{
data_file.WriteLine(location);
}
Xamarin's SQLite.Net component has documentation that demonstrates how to create and utilize a db from within your app.
string folder = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
var conn = new SQLiteConnection (System.IO.Path.Combine (folder, "stocks.db"));
I have a method that creates a virtual directory. How can I set the .NET Framework to version 2 while I create the virtual directory?
My method looks like this so far:
private static void CreateVDir(string metabasePath, string vDirName, string physicalPath)
{
// metabasePath is of the form "IIS://<servername>/<service>/<siteID>/Root[/<vdir>]"
// for example "IIS://localhost/W3SVC/1/Root".
// vDirName is of the form "<name>", for example, "MyNewVDir".
// physicalPath is of the form "<drive>:\<path>", for example, "C:\Inetpub\Wwwroot".
Console.WriteLine("\nCreating virtual directory {0}/{1}, mapping the Root application to {2}:",
metabasePath, vDirName, physicalPath);
DirectoryEntry site = new DirectoryEntry(metabasePath);
string className = site.SchemaClassName;
if ((className.EndsWith("Server")) || (className.EndsWith("VirtualDir")))
{
DirectoryEntries vdirs = site.Children;
DirectoryEntry newVDir = vdirs.Add(vDirName, (className.Replace("Service", "VirtualDir")));
newVDir.Properties["Path"][0] = physicalPath;
newVDir.Properties["AccessScript"][0] = true;
// These properties are necessary for an application to be created.
newVDir.Properties["AppFriendlyName"][0] = vDirName;
newVDir.Properties["AppIsolated"][0] = "1";
newVDir.Properties["AppRoot"][0] =
"/LM" +
metabasePath.Substring(metabasePath.IndexOf("/", ("IIS://".Length)));
newVDir.CommitChanges();
Console.WriteLine(" Done.");
}
else
Console.WriteLine(
" Failed. A virtual directory can only be created in a site or virtual directory node.");
}
The "ScriptMaps" property is where the configuration mappings get stored. That is, that's where you can map *.aspx files to get processed by ASP.NET. An example is in Creating ISAPI Mappings Programmatically.
After you have created the virtual directory, you can run aspnet_regiis -s from the .NET framework directory of your choice.
On my sytem, the command would look something like this:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis -s W3SVC/1/ROOT/SampleApp1
I have done this from a custom action in my installer successfully.