Windows Store App c# replace SQL Database in local storage - c#

I am trying to overwrite the database in my local folder with one that is in my pictures directory I use the following
StorageFolder storageFolder = KnownFolders.PicturesLibrary;
String picName = "SqlLiteWin8-1.db";
var file2 = await storageFolder.TryGetItemAsync(picName) as IStorageFile;
StorageFile fileCopy = await file2.CopyAsync(Windows.Storage.ApplicationData.Current.LocalFolder, "SqlLiteWin8-1.db", Windows.Storage.NameCollisionOption.ReplaceExisting);
It seems to work and the file is copied and overwrite the old one
Problem is when I run the app it still shows the old data
I checked by manually deleting the db in the local state folder of the app then running the code and it copies it to the folder.
I think its still using the database in the app package and not the one in the local folder
The database in the pictures directory is identical to the one stored in the app except 1 record is modified
I want to overwrite it so that I can just supply a new db file to users and the app will use the new data or is there a way of bypassing this and read the DB straight from the pictures directory instead of the local folder
one though was it uses the following code to check if the db exists and copies if it doesnt could this be what is causing it not to work
public static async Task<bool> checkDataBaseConnection()
{
bool isDatabaseExisting = false;
try
{
var uri = new Uri("ms-appx:///SqlLiteWin8-1.db"); //in application folder
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
var destinationFolder = ApplicationData.Current.LocalFolder;//local appdata dir
//await file.DeleteAsync();
// var f = await destinationFolder.GetFileAsync("data.db3");
await file.CopyAsync(destinationFolder);
}
catch (Exception ex)
{
throw ex;
isDatabaseExisting = false;
}
if (!isDatabaseExisting)
{
StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync("AFSMOJO.db");
await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder);
}
return isDatabaseExisting;
}
As always your help is greatly appreciated
Mark

Ignore my stupidity I found what was wrong I was connecting to the internal database instead of the local one
I changed
var db = new SQLiteConnection("SqlLiteWin8-1.db");
to
var db = new SQLiteConnection(Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "SqlLiteWin8-1.db"));
and now i can change my db in the picture folder and it copies it to the local one and uses the new data
Thanks
Mark

Related

Unable to move directory in azure using ShareDirectoryClient

Normally we can move the directory using
// source is: "C:\Songs\Elvis my Man"
// newLocation is: "C:\Songs\Elvis"
try
{
// Previous command was: Directory.Move(source, newLocation);
DirectoryInfo dir = new DirectoryInfo(source);
dir.MoveTo(newLocation);
}
catch (Exception e)
{
Console.WriteLine("Error: "+ e.Message);
}
Now, when using the azure:
string myconnectionString = ConfigurationManager.ConnectionStrings["StorageConnection"].ConnectionString.ToString();
string myshareName = "Mysampleshare";
string mydirName = "Mysampledir";
// Get a reference to a share and then create it
ShareClient myshare = new ShareClient(myconnectionString, myshareName);
ShareDirectoryClient directory1 = myshare.GetDirectoryClient(mydirName);
string myshareName2 = "Mysampleshare2";
string mydirName2 = "Mysampledir2";
// Get a reference to a share and then create it
ShareClient myshare2 = new ShareClient(myconnectionString, myshareName2);
ShareDirectoryClient directory2 = myshare2.GetDirectoryClient(mydirName2);
Directory.Move(directory1.Path, directory2.Path);
I am unable to move the directory from one location to another using azure. I am getting exception.
DirectoryNotFoundException: The path specified by sourceDirName is invalid
Please suggest your advice.
ShareDirectoryClient essentially implements Azure File Service REST API thus you cannot use System.IO operations like Directory.Move with it.
There are two possible solutions:
If you want to use the SDK, what you will need to do is list files and directories recursively in the source directory and then copy individual files from source directory to target directory. You will also need to create directories in the target directory as well. Once the copy operation is complete, then you will need to delete all files and directories from the source directory. Once the source directory is empty, only then you will be able to delete the source directory.
You will need to do all this because the REST API does not natively support move operation. To accomplish move, you will need to perform copy operation followed by delete operation.
If you want to use System.IO, then you will need to mount the file share as a shared network drive so that you can get a drive letter assigned to that file share. Once you have that, then you will be able to use operations like Directory.Move available in System.IO namespace.
UPDATE
Please try the code below:
using System;
using System.Threading.Tasks;
using Azure.Storage.Files.Shares;
namespace SO69798149
{
class Program
{
const string MyconnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key";
const string MyshareName = "share-name";
const string SourceDirectoryName = "source-directory-name";
private const string RenamedDirectoryName = "new-directory-name";
static async Task Main(string[] args)
{
ShareClient myshare = new ShareClient(MyconnectionString, MyshareName);
ShareDirectoryClient sourceDirectoryClient = myshare.GetDirectoryClient(SourceDirectoryName);
ShareDirectoryClient targetDirectoryClient = myshare.GetDirectoryClient(RenamedDirectoryName);
await RenameDirectory(sourceDirectoryClient, targetDirectoryClient);
Console.WriteLine("Directory renamed.");
}
static async Task RenameDirectory(ShareDirectoryClient sourceDirectoryClient,
ShareDirectoryClient targetDirectoryClient)
{
//Create target directory
await targetDirectoryClient.CreateIfNotExistsAsync();
//List files and folders from the source directory
var result = sourceDirectoryClient.GetFilesAndDirectoriesAsync();
await foreach (var items in result.AsPages())
{
foreach (var item in items.Values)
{
if (item.IsDirectory)
{
//If item is directory, then get the child items in that directory recursively.
await RenameDirectory(sourceDirectoryClient.GetSubdirectoryClient(item.Name),
targetDirectoryClient.GetSubdirectoryClient(item.Name));
}
else
{
//If item is file, then copy the file and then delete it.
var sourceFileClient = sourceDirectoryClient.GetFileClient(item.Name);
var targetFileClient = targetDirectoryClient.GetFileClient(item.Name);
await targetFileClient.StartCopyAsync(sourceFileClient.Uri);
await sourceFileClient.DeleteIfExistsAsync();
}
}
}
//Delete source directory.
await sourceDirectoryClient.DeleteIfExistsAsync();
}
}
}

WinSCP.Net, folder is not copied from remote to local

I have been using WinSCP to download files, periodically, from a Unix server to Windows server and it has been working with no issues. I also check if remote file is older or already exists (don't copy).
Now, I have to do the same but this time I have to download files and folders. Files are copied fine but folders aren't. When playing with the settings, I got it to copy the contents of the folder but they get copied to my root local folder; I thought WinSCP would copy everything.
In below code, LocalFolder is Z:\My_Data and LogRootFolder is /xyz/gtc/a00/
Folder structure on remote is /xyz/gtc/a00/ABCD/outcomes/ with subfolder "backup" that has many subfolders named as dates (e.g. /xyz/gtc/a00/ABCD/outcomes/backup/2021-06-23/)
Either none of "backup/2021-xx-xx/" files and folder are copied, or they are all copied to Z:\My_Data\ABCD
After setting up the session, called SFTP_Session:
string sRemotePath = LogRootFolder + "ABCD/outcomes/";
string sLocalFolder = Path.Combine(LocalFolder, #"ABCD\");
if (SFTP_Session.Opened)
{
using (SFTP_Session)
{
SFTP_Session.QueryReceived += (sender, e) =>
{
...
e.Continue();
};
//var opts = EnumerationOptions.EnumerateDirectories | EnumerationOptions.AllDirectories;
//IEnumerable<RemoteFileInfo> fileInfos = SFTP_Session.EnumerateRemoteFiles(sRemotePath, "*.dat", opts); <-- This copies files in folder(s) to m local root folder
Regex mask = new Regex(#"\.(dat|err)$", RegexOptions.IgnoreCase);
IEnumerable<RemoteFileInfo> fileInfos =
SFTP_Session.EnumerateRemoteFiles(sRemotePath, null, EnumerationOptions.AllDirectories)
.Where(fileInfo => mask.Match(fileInfo.Name).Success)
.ToList();
foreach (RemoteFileInfo fileInfo in fileInfos)
{
string localFilePath = Path.Combine(sLocalFolder, fileInfo.Name);
if (fileInfo.IsDirectory)
{
// Create local subdirectory, if it does not exist yet
if (!Directory.Exists(localFilePath))
{
Directory.CreateDirectory(localFilePath);
}
}
else
{
string remoteFilePath = RemotePath.EscapeFileMask(fileInfo.FullName);
// If file does not exist in local folder, download
if (!File.Exists(localFilePath))
{
bDownload = true;
}
else // If file exists in local folder but is older, download; else skip
{
DateTime remoteWriteTime = SFTP_Session.GetFileInfo(remoteFilePath).LastWriteTime;
DateTime localWriteTime = File.GetLastWriteTime(localFilePath);
if (remoteWriteTime > localWriteTime)
{
bDownload = true;
}
else
{
bDownload = false;
}
}
if (bDownload)
{
// Download file
TransferOptions oTrRes = new TransferOptions();
oTrRes.TransferMode = TransferMode.Automatic; //The Transfer Mode - Automatic, Binary, or Ascii
oTrRes.FilePermissions = null; //Permissions applied to remote files; null for default permissions. Can set user, Group, or other Read/Write/Execute permissions.
oTrRes.PreserveTimestamp = false; //Set last write time of destination file to that of source file - basically change the timestamp to match destination and source files.
oTrRes.ResumeSupport.State = TransferResumeSupportState.Off;
TransferOperationResult transferResult = SFTP_Session.GetFiles(remoteFilePath, localFilePath, false, oTrRes);//.Replace("\\","")); // I thought this would get files AND folders
// Throw on any error
transferResult.Check();
foreach (TransferEventArgs transfer in transferResult.Transfers)
{
// Store local file info in a data table for processing later
...
}
SessionRemoteExceptionCollection srec = transferResult.Failures;
foreach (SessionRemoteException sre in srec)
{
// Log errors
}
// Did the download succeeded?
if (!transferResult.IsSuccess)
{
// Log error (but continue with other files)
}
}
}
}
At the end, in local folder I see the files downloaded and copied and subfolders that I created (using above code) but no files in those folders. Can't see what I am missing here.
Your code basically synchronizes a remote directory to a local one.
Instead of fixing your code, you can simply replace most of it with a simple call to Session.SynchronizeDirectories:
https://winscp.net/eng/docs/library_session_synchronizedirectories
Try the synchronization first in WinSCP GUI to see if it does what you need.
If you need to do some processing with the synchronized files, use the SynchronizationResult returned by Session.SynchronizeDirectories. It contains a list of all synchronized files.
If you need to exclude some files from the synchronization, use TransferOptions.FileMask.

Downloading images from publicly shared folders and sub-folders on Dropbox

This is similar to my previous question:
Downloading images from publicly shared folder on Dropbox
I have this piece of code (simplified version) that needs to download all images from publicly shared folder and all sub-folders.
using Dropbox.Api;
using Dropbox.Api.Files;
...
// AccessToken - get it from app console
// FolderToDownload - https://www.dropbox.com/sh/{unicorn_string}?dl=0
using (var dbx = new DropboxClient(_dropboxSettings.AccessToken))
{
var sharedLink = new SharedLink(_dropboxSettings.FolderToDownload);
var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink);
// var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink, recursive: true);
// "recursive: true" throws: Error in call to API function "files/list_folder": Recursive list folder is not supported for shared link.
foreach (var entry in sharedFiles.Entries)
{
if (entry.IsFile)
{
var link = await dbx.Sharing.GetSharedLinkFileAsync(url: _dropboxSettings.FolderToDownload, path: "/" + entry.Name);
var byteArray = await link.GetContentAsByteArrayAsync();
}
if (entry.IsFolder)
{
var subFolder = entry.AsFolder;
// var folderContent = await dbx.Files.ListFolderAsync(path: subFolder.Id);
// var subFolderSharedLink = new SharedLink(???);
}
}
}
How do I list entries of all sub-folders?
For any given subfolder, to list its contents, you'll need to call back to ListFolderAsync again, using the same sharedLink value, but supplying a path value for the subfolder, relative to the root folder for the shared link.
For example, if you list the contents of the folder shared link, and one of the entries is a folder with the name "SomeFolder", to then list the contents of "SomeFolder", you would need to make a call like:
await dbx.Files.ListFolderAsync(path: "/SomeFolder", sharedLink: sharedLink);

How can I create a database file with SQLite-net?

I am using SQLite-net nuget package in my UWP application. I want to create a local database file to use as such:
var s = new SQLiteConnection("myDbSQLite.db3", SQLiteOpenFlags.Create);
But it throws the error:
Could not open database file:
C:\Path\MyProject\bin\x86\Debug\AppX\myDbSQLite.db3 (Misuse)
I see in other posts they suggest to use SQLiteConnection.CreateFile("MyDatabase.sqlite"); but I don't see that method?
EDIT
The code
FileStream fs = File.Create(path);
Throws the exception:
UnauthorizedAccessException access to the path is denied
So I think this is a permission issue I am having with UWP. Is there something in the capabilities that I need to set?
Check your permissions on the folder, and also try using this for the constructor
_database = new SQLiteAsyncConnection(
"myDbSQLite.db3",
SQLiteOpenFlags.Create |
SQLiteOpenFlags.FullMutex |
SQLiteOpenFlags.ReadWrite );
Because creating a file in UWP must be done with the UWP API, if you're going to use this nuget library, you have to accommodate by creating it yourself first:
// Create the empty file; replace if exists.
Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
storageFolder.CreateFileAsync("myDbSQLite.db3", Windows.Storage.CreationCollisionOption.ReplaceExisting);
My UWP app is actually part of a Xamarin.Forms app that is using shared code, so if your app is solely UWP there's probably a better library, such as this one that Codexer referred.
You should use a folder wher you have write-access to. So please try the following code:
String path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string dbFile = Path.Combine( path, "myDbSQLite.db3");
var s = new SQLiteConnection( dbFile, SQLiteOpenFlags.Create);
This worked for me:
var databasePath = Path.Combine(GetLocalFileDirectory(), "MyData.db");
try
{
// Create the empty file; replace if exists.
db = new SQLiteAsyncConnection(databasePath,
SQLiteOpenFlags.Create |
SQLiteOpenFlags.FullMutex |
SQLiteOpenFlags.ReadWrite);
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
public string GetLocalFileDirectory()
{
var docFolder = FileSystem.AppDataDirectory
var libFolder = Path.Combine(docFolder, "Databases");
if (!Directory.Exists(libFolder))
{
Directory.CreateDirectory(libFolder);
}
return libFolder;
}

Get all files inside a specific folder in a library with UWP

I'm trying to get all the videos in a specific folder inside the Videos library using UWP, right now I can get all videos inside the Videos library, but I'd like to reduce my results to only those inside the specified folder. My code is this:
Windows.Storage.Search.QueryOptions queryOption = new QueryOptions(CommonFileQuery.OrderByTitle, new string[] {".mp4"});
queryOption.FolderDepth = FolderDepth.Deep;
var files = await KnownFolders.VideosLibrary.CreateFileQueryWithOptions(queryOption).GetFilesAsync();
StorageFile videoToPlay = (files[new Random().Next(0, files.Count)] as StorageFile);
var stream = await videoToPlay.OpenAsync(Windows.Storage.FileAccessMode.Read);
Player.SetSource(stream, videoToPlay.ContentType);
Debug.WriteLine(Player.Source);
How could I access a subfolder named "Videos to Play" and then get all the videos inside that folder? I tried accesing it by using a path like:
string localfolder = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
var array = localfolder.Split('\\');
var username = array[2];
string[] allVideos = System.IO.Directory.GetFiles("C:/Users/" + username + "/Videos/Videos to Play");
But I get access denied even though I already requested access to the Videos library (and the fact that the first example works shows that I actually have access to it).
try
{
var folder = await KnownFolders.VideosLibrary.GetFolderAsync("Videos to Play");
}
catch (FileNotFoundException exc)
{
// TODO: Handle the case when the folder wasn't found on the user's machine.
}
In the folder variable you'll have the reference to the desired folder. Then it's the very same stuff that you already do, but instead of KnownFolders.VideosLibrary folder use this one!

Categories