SQLite encryption in Microsoft.EntityFrameWork - sqlite

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.

Related

SQLite encryption in Universal Windows apps

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.

Can't find a working example of SQLite.Net-PCL in Xamarin Forms

I can't seem to get off dead center with SQLite.Net-PCL; I have a Xamarin forms solution with a PCL proj, Droid proj, iOS proj, and Windows Universal project. I have installed the nuget packages for SQLite.Net-PCL and SQLite.Net.Core-PCL.
So, I go over to the github project to find some awesome examples to get started and none of them work; apparently you have to pass a platform into the database connection, but I get a reference error on them all (such as SQLitePlatformWin32).
Search the web for the references and... nothing. Search nuget for the platforms and... nothing.
What am I missing? (yes, I feel dumb)
An example they have is
public class Database : SQLiteConnection
{
public Database(string path) : base(new SQLitePlatformWin32(), path)
{
CreateTable<Stock>();
CreateTable<Valuation>();
}}
and I get a reference error that I can't resolve on the "new SQLitePlatformWin32" line.
For anyone else struggling, here is what you need to do.
Install the SQLite.Net-PCL, SQLite.Net.Core-PCL and SQLite.Net.Async-PCL nugets
Create an interface for ISQLite in your PCL:
public interface ISQLite
{
SQLiteConnection GetConnection();
}
Call GetConnection via DependencyService
PatientDatabase = DependencyService.Get<ISQLite>().GetConnection();
PatientDatabase.CreateTable<Patient>();
The above will create the connection based on your platform (i.e. android, ios). In each platform's project, you must have a GetConnection that is accessable via DependencyService such as this for Android
[assembly: Xamarin.Forms.Dependency(typeof(SQLite_Android))]
// ...
public class SQLite_Android : ISQLite
{
public SQLite_Android() { }
public SQLite.Net.SQLiteConnection GetConnection()
{
var sqliteFilename = "TodoSQLite.db3";
string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); // Documents folder
var path = Path.Combine(documentsPath, sqliteFilename);
// Create the connection
var conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), path);
// Return the database connection
return conn;
}
}
My problem was I was trying to create the connection in my PCL and I couldn't find the platforms, what you need to do is create the connection in each individual project.

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..
}

Repository pattern with mvc without entity framework

Is repository pattern with unit of work best fit for entity framework application?
I am creating a new asp.net mvc application and i want to use stored procedure (microsoft enterprise library) instead of Entity framework(or any other ORM).
So how can i use repository pattern with mvc application?
I have explored many tutorials but not getting expected result. Please suggest me better approach for n tier application.
You have to understand that "repository pattern" is just an idea to organize your code. I think you can still use it without any problem.
I just want to provide you an example of implementation using sql stored procedure: suppose you have to manage the classic table "Contacts".
You can create your UnitOfWork contract:
public interface IContactsRepository {
void AddContact(Contact c);
void RemoveContact(Contact c);
void UpdateContact(Contact c);
void Search(string keyword);
}
After, you can create your own implementation without using EF:
public sealed class SPContactsRepository : IContactsRepository {
// Is just an exampl.e
public void AddContact(Contact c) {
var sqlCommnad = new SqlCommand(this._connectionString);
sqlCommand.CommandText = "dbo.AddContact";
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.AddParameter("Name", c.Name);
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQuery();
}
}
Hope this can help!
So just to continue what Roberto already started, your controller in the MVC app will look like this:
public class ContactsController : Controller
{
private readonly IContactsRepository _contactsRepo;
public ContactsController(IContactsRepository repo)
{
_contactsRepo = repo;
}
}
These pattern uses dependency injection(DI). There are several options for DI container. You can use Unity which is a Microsoft package that you can install via nuget package manager to your MVC web project. The install will create a UnityConfig.cs file in your App_Start folder. You can register the dependency as:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IContactsRepository, SPContactsRepository>();
}
And in your Global.asax.cs file inside Application_Start(), you initialize the container:
UnityConfig.RegisterComponents();
If you use EF, the DbContext is already your Unit of Work and the DbSet as your repository. Having said that, you should not create a repository that will add another layer of data abstraction. Instead, you can create, domain services.

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.

Resources