SQLite encryption in Universal Windows apps - sqlite

I am using SQLite database in my universal app. I want to make password protection for the DB file. I am able to set the password for the db file. But when I am trying to read it it shows error like "Sqlite26: file is encrypted or not a database file".
I referred to this URL. I am using Entity Framework Core in the .NET Standard library. Is it possible to read the value from the encrypted DB in .NET Standard library?

The author of the article you linked actually has an answer here on SO that deals with the EF Core scenario as well. You can open the database with EF Core in the OnConfiguring method override:
class AppDbContext : DbContext
{
private SqliteConnection _connection;
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
_connection = new SqliteConnection(_connectionString);
_connection.Open();
var command = _connection.CreateCommand();
command.CommandText = "PRAGMA key = 'password';";
command.ExecuteNonQuery();
options.UseSqlite(_connection);
}
protected override void Dispose()
{
_connection?.Dispose();
}
}
The kez is to provide the password as in a PRAGMA command before the first query on the connection.

Related

SQLite encryption in Microsoft.EntityFrameWork

I’m currently trying to encrypt SQLite database with official SEE extension when using Microsoft entity framework.
I’m able to encrypt database when using ADO.NET. However getting an error “You specified a password in the connection string, but the native SQLite library ‘e_sqlite3’ doesn’t support encryption”
when using entity frame work.
Nuget Packages Used:
[Microsoft.EntityFrameWork.Core Microsoft.EntityFrameWork.Core.SQLite SQLite.Encryption.Extension System.Data.SQLite.Core]
Please can you advise how to fix this error with official SEE extension?
CustomDBContext.cs:
private readonly bool _created = false;
public CustomDbContext(DBContextOptions<CustomDbContext> options):base(options){
if(!_created)
{
_created = true;
Database.EnsureCreated();
}
}
public DbSet<SampleEntity> SampleEntities {get; set;}
Program.cs:
static void Main(string[] args)
{
var services = new ServiceCollection();
ConfigureService(services);
using ServiceProvider provider = services.BuildServiceProvider();
provider.GetService<ICustomDBContext>();
}
private static void ConfigureServices(ServiceCollection services)
{
string password = Convert.ToHexString(Encoding.Default.GetBytes("aes256:test");
SQLiteCommand.Execute("PRAGMA activate_extensions='see-7bb07b8d471d642e'", SQLiteExecuteType.NonQuery,#"Data Source=c:\users\test.db");
SQLiteConnectionStringBuilder connectionStringBuilder = new(){
ConnectionString = #"Data Source=c:\users\test.db;Password="+password};
SQLiteConnection conn = new(connectionStringBuilder.ConnectionString);
connection.Open();
connection.ChangePassword(password);
services.AddDbContext<CustomDBContext>(options => options.UseSqlite(connection));
}
To use official SQLite extension for encryption, please choose the entity framework until EF6 since the System.Data.SQLite library supports only till EF6 and there is no direct support for EF core.
If we still need to use entity framework core then use we can also consider other options like encryption using SQLCipher that supports EF core.

AspNet Core Add Migration - ConnectionString is from database

I am working with AspNet Core 2.0, I have a situation where I have a context but the connection string is dynamic as per selected by the user at runtime.
Add-Migration doesn't work as it wants to have the connection string to match migration history.
var datastore = _MainDBContext.datastores.FirstOrDefault(x=>x.db_type=="MS");
string connectionString = #"Server=" + datastore.db_instance_ip + ";Port=3306;Database=" + datastore.db_name + ";Uid=" + datastore.db_user + ";Password=" + datastore.db_pass + ";";
optionsBuilder.UseMySQL(connectionString);
_MSDBContext= new MSDBContext(optionsBuilder.Options);
_MSDBContext.Database.Migrate();
Error
No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.
I want the migrate to create the database along with tables dynamically. Any help is appreciated.
Thanks
The error message says your DbContext needs a constructor which accepts a DbContextOptions.
public MSDBContext(DbContextOptions options) : base(options)
{
}
Or you could try the following approach (inside of your context class):
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString = configuration.GetConnectionString("NAME_OF_CONNECTION_STRING");
optionsBuilder.UseSqlServer(connectionString); //or any other DB provider
}
}
Of course, you can use different logic to get the connection string. You don't need to use appsettings.json file.

ASP.NET Core Data Access (EF6, EF Core 1.0)

I have been really excited about using ASP.NET Core 1.0 and can't wait to create some production apps. The one issue I have is the Data Access, using MVC5 and EF6 made it really easy to create an .edmx file and have your Stored Procedures mapped (complex types), a fantastic feature which makes it really easy for us to access data.
EF Core 1.0 github page says that it will implement Stored procedure mapping.
I have seen examples where you write your query but I want to prevent SQL Injection.
What is the best way to call a Stored Procedures with EF6 using .NET Core 1.0 with the full .NET framework?
One possible work around is to use a Class Library which you can add your EF6 ADO.NET Entity Data Model to.
Class Library (DataAccessLayer)
Add your connection string data here
namespace DataAccessLayer
{
public class Class1
{
public static DbConnection GetConnectionString()
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Metadata = "res://*/Models.devModel.csdl|res://*/Models.devModel.ssdl|res://*/Models.devModel.msl";
entityBuilder.ProviderConnectionString = "data source=dev-server;initial catalog=ProductWorkflow_New;persist security info=True;user id=user;password=password;MultipleActiveResultSets=True;App=EntityFramework";
entityBuilder.Provider = "System.Data.SqlClient";
return new EntityConnection(entityBuilder.ToString());
}
}
}
devModel.Context.cs (devModel.edmx)
public partial class devModelEntities : DbContext
{
public devModelEntities()
// Add static method here
: base(Class1.GetConnectionString(), true)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
// Your generated code..
}

EF7 + ASP.NET5 beta8 - Database initializers

I'm working on multitenant application (ASP.NET 5 + EF7). Each tenant will have separate database. I will have one separate database for tenant account data. I have registered service for EF in startup class for this separate database. I have problem with migrations. I cant create EF migration, until tenantDbContext is registered as service with specific connection string. But this conection string must be dynamic for each tenant... Any idea please? What is the best option to manage DbContexts for tenants?
Future edit - protected override void OnConfiguring was the key how to do: Is this good solution please?
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<TenantDbContext>();
public class TenantDbContext : IdentityDbContext<ApplicationUser>
{
public TenantDbContext() //development database with no connectionString in constructor
{
this._connectionString = "Connection String";
}
public TenantDbContext(string ConnectionString)
{
this._connectionString = ConnectionString;
}
private string _connectionString { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connectionString);
}
...etc
As I mentioned in comments I have not tried multi-tenant/multi-db myself but try the following:
You can use DbContext CreateIfNotExists() method. https://msdn.microsoft.com/en-us/library/system.data.entity.database.createifnotexists(v=vs.113).aspx
If you have a Migrations/Configuration.cs you can set AutomaticMigrationsEnabled property to false
Setting the initializer off is probably needed as well: Database.SetInitializer<DatabaseContext>(null);
Sorry without knowing more details like workflow of creating a new tenant (automatic from DB or is a screen filled out with the connection string and name etc.) I can't make more detailed suggestions. I would suggest that your data layer be quite abstracted from the context. It seems like a bad idea for developers to have to select the correct context. Hence the use of a factory.
An option is always requiring a tenant id to be passed into all service or repository methods. I'm guessing this would be in some kind of user claim available in the controller.

NHibernate, SQLite and ATTACH DATABASE

I'm trying to do something slightly unusual... I currently have a SQLite database, accessed with NHibernate. This database is frequently uploaded to a server. I have a new requirement to create a new table for reporting purposes, which is expected to become pretty big. This table doesn't need to be uploaded to the server, so I'd like to put it in a separate database, and use ATTACH DATABASE to access it transparently from my main database.
The problem is I don't know how to do that with NHibernate... How can I tell NHibernate to attach the other database when it connects? I can't find any connection string parameter or NH configuration property allowing to do that... is it even possible?
An acceptable option would be to manually execute the ATTACH DATABASE command when the connection is open, but I don't know how to do that. When I build the NH session factory, it immediately tries to update the schema (hbm2ddl.auto = update), and I don't have an opportunity to do anything with the connection before that. So it will just try to create the new table on my main database, which of course is not what I want...
Has anybody ever done that before? How did you do it?
Thanks
EDIT: In case someone needs to do the same, here's my solution, inspired by Diego's answer
Connection provider:
public class AttachedDbConnectionProvider : DriverConnectionProvider
{
private string _attachedDbAlias;
private string _attachedDbFileName;
public override IDbConnection GetConnection()
{
var connection = base.GetConnection();
if (!string.IsNullOrEmpty(_attachedDbAlias) && !string.IsNullOrEmpty(_attachedDbFileName))
{
using (var attachCommand = connection.CreateCommand())
{
attachCommand.CommandText = string.Format(
"ATTACH DATABASE '{0}' AS {1}",
_attachedDbFileName.Replace("'", "''"),
_attachedDbAlias);
attachCommand.ExecuteNonQuery();
}
}
return connection;
}
public override void Configure(IDictionary<string, string> settings)
{
base.Configure(settings);
settings.TryGetValue("connection.attached_db_alias", out _attachedDbAlias);
settings.TryGetValue("connection.attached_db_filename", out _attachedDbFileName);
}
}
Configuration file:
<property name="connection.provider">MyApp.DataAccess.AttachedDbConnectionProvider, MyApp.DataAccess</property>
<property name="connection.attached_db_alias">reportdb</property>
<property name="connection.attached_db_filename">mydatabase.report.db</property>
Now, to map a class to a table in the attached database, I just need to specify "reportdb." in the mapping file
This might help...
public class MyConnectionProvider : DriverConnectionProvider
{
public override IDbConnection GetConnection()
{
var connection = base.GetConnection();
var attachCommand = connection.CreateCommand();
attachCommand.CommandText = "ATTACH DATABASE FOO";
attachCommand.ExecuteNonQuery();
return connection;
}
}
Config:
<property name="connection.provider">MyConnectionProvider, MyAssembly</property>

Resources