Try your search with a different keyword or use * as a wildcard.
using System.Data;
using System.Data.Common;
using System.Linq.Expressions;
using System.Text;
using LinqToDB;
using LinqToDB.Data;
using LinqToDB.DataProvider;
using LinqToDB.DataProvider.SQLite;
using LinqToDB.Tools;
using Microsoft.Data.Sqlite;
using Nop.Core;
using Nop.Core.ComponentModel;
using Nop.Data;
using Nop.Data.DataProviders;
namespace Nop.Tests;
///
/// Represents the SQLite data provider
///
public partial class SqLiteNopDataProvider : BaseDataProvider, INopDataProvider
{
#region Consts
//it's quite fast hash (to cheaply distinguish between objects)
private const string HASH_ALGORITHM = "SHA1";
private static DataConnection _dataContext;
private static readonly ReaderWriterLockSlim _locker = new();
#endregion
#region Methods
public void CreateDatabase(string collation, int triesToConnect = 10)
{
ExecuteNonQueryAsync("PRAGMA journal_mode=WAL;").Wait();
}
///
/// Gets a connection to the database for a current data provider
///
/// Connection string
/// Connection to a database
protected override DbConnection GetInternalDbConnection(string connectionString)
{
ArgumentException.ThrowIfNullOrEmpty(connectionString);
return new SqliteConnection(string.IsNullOrEmpty(connectionString)
? DataSettingsManager.LoadSettings().ConnectionString
: connectionString);
}
///
/// Inserts record into table. Returns inserted entity with identity
///
///
///
/// Inserted entity
public override TEntity InsertEntity(TEntity entity)
{
using (new ReaderWriteLockDisposable(_locker))
{
entity.Id = DataContext.InsertWithInt32Identity(entity);
return entity;
}
}
///
/// Insert a new entity
///
/// Entity type
/// Entity
/// Entity
public override Task InsertEntityAsync(TEntity entity)
{
InsertEntity(entity);
return Task.FromResult(entity);
}
///
/// Updates record in table, using values from entity parameter.
/// Record to update identified by match on primary key value from obj value.
///
/// Entity with data to update
/// Entity type
public override Task UpdateEntityAsync(TEntity entity)
{
using (new ReaderWriteLockDisposable(_locker))
DataContext.Update(entity);
return Task.CompletedTask;
}
///
/// Updates records in table, using values from entity parameter.
/// Records to update are identified by match on primary key value from obj value.
///
/// Entities with data to update
/// Entity type
/// A task that represents the asynchronous operation
public override async Task UpdateEntitiesAsync(IEnumerable entities)
{
foreach (var entity in entities)
await UpdateEntityAsync(entity);
}
///
/// Updates records in table, using values from entity parameter.
/// Records to update are identified by match on primary key value from obj value.
///
/// Entities with data to update
/// Entity type
public override void UpdateEntities(IEnumerable entities)
{
foreach (var entity in entities)
UpdateEntity(entity);
}
///
/// Deletes record in table. Record to delete identified
/// by match on primary key value from obj value.
///
/// Entity for delete operation
/// Entity type
public override Task DeleteEntityAsync(TEntity entity)
{
using (new ReaderWriteLockDisposable(_locker))
DataContext.Delete(entity);
return Task.CompletedTask;
}
///
/// Performs delete records in a table
///
/// Entities for delete operation
/// Entity type
public override Task BulkDeleteEntitiesAsync(IList entities)
{
using (new ReaderWriteLockDisposable(_locker))
{
foreach (var entity in entities)
DataContext.Delete(entity);
}
return Task.CompletedTask;
}
///
/// Performs delete records in a table by a condition
///
/// A function to test each element for a condition.
/// Entity type
public override Task BulkDeleteEntitiesAsync(Expression> predicate)
{
return Task.FromResult(DataContext.GetTable()
.Where(predicate).Delete());
}
///
/// Performs bulk insert operation for entity collection.
///
/// Entities for insert operation
/// Entity type
public override Task BulkInsertEntitiesAsync(IEnumerable entities)
{
using (new ReaderWriteLockDisposable(_locker))
DataContext.BulkCopy(new BulkCopyOptions(), entities.RetrieveIdentity(DataContext));
return Task.CompletedTask;
}
///
/// Gets the name of a foreign key
///
/// Foreign key table
/// Foreign key column name
/// Primary table
/// Primary key column name
/// Name of a foreign key
public string CreateForeignKeyName(string foreignTable, string foreignColumn, string primaryTable, string primaryColumn)
{
return "FK_" + HashHelper.CreateHash(Encoding.UTF8.GetBytes($"{foreignTable}_{foreignColumn}_{primaryTable}_{primaryColumn}"), HASH_ALGORITHM);
}
///
/// Gets the name of an index
///
/// Target table name
/// Target column name
/// Name of an index
public string GetIndexName(string targetTable, string targetColumn)
{
return "IX_" + HashHelper.CreateHash(Encoding.UTF8.GetBytes($"{targetTable}_{targetColumn}"), HASH_ALGORITHM);
}
///
/// Returns queryable source for specified mapping class for current connection,
/// mapped to database table or view.
///
/// Entity type
/// Queryable source
public override IQueryable GetTable()
{
using (new ReaderWriteLockDisposable(_locker, ReaderWriteLockType.Read))
return DataContext.GetTable();
}
///
/// Get the current identity value
///
/// Entity
/// Integer identity; null if cannot get the result
public Task GetTableIdentAsync() where TEntity : BaseEntity
{
using (new ReaderWriteLockDisposable(_locker, ReaderWriteLockType.Read))
{
var tableName = DataContext.GetTable().TableName;
var result = DataContext.Query($"select seq from sqlite_sequence where name = \"{tableName}\"")
.FirstOrDefault();
return Task.FromResult(result ?? 1);
}
}
///
/// Checks if the specified database exists, returns true if database exists
///
/// Returns true if the database exists.
public bool DatabaseExists()
{
return true;
}
///
/// Creates a backup of the database
///
public virtual Task BackupDatabaseAsync(string fileName)
{
throw new DataException("This database provider does not support backup");
}
///
/// Restores the database from a backup
///
/// The name of the backup file
public virtual Task RestoreDatabaseAsync(string backupFileName)
{
throw new DataException("This database provider does not support backup");
}
///
/// Re-index database tables
///
public Task ReIndexTablesAsync()
{
using (new ReaderWriteLockDisposable(_locker))
DataContext.Execute("VACUUM;");
return Task.CompletedTask;
}
///
/// Build the connection string
///
/// Connection string info
/// Connection string
public string BuildConnectionString(INopConnectionStringInfo nopConnectionString)
{
ArgumentNullException.ThrowIfNull(nopConnectionString);
if (nopConnectionString.IntegratedSecurity)
throw new NopException("Data provider supports connection only with password");
var builder = new SqliteConnectionStringBuilder
{
DataSource = CommonHelper.DefaultFileProvider.MapPath($"~/App_Data/{nopConnectionString.DatabaseName}.sqlite"),
Password = nopConnectionString.Password,
Mode = SqliteOpenMode.ReadWrite,
Cache = SqliteCacheMode.Shared
};
return builder.ConnectionString;
}
///
/// Set table identity (is supported)
///
/// Entity
/// Identity value
public Task SetTableIdentAsync(int ident) where TEntity : BaseEntity
{
using (new ReaderWriteLockDisposable(_locker))
{
var tableName = DataContext.GetTable().TableName;
DataContext.Execute($"update sqlite_sequence set seq = {ident} where name = \"{tableName}\"");
}
return Task.CompletedTask;
}
///
/// Executes command using System.Data.CommandType.StoredProcedure command type and
/// returns results as collection of values of specified type
///
/// Result record type
/// Procedure name
/// Command parameters
/// Returns collection of query result records
public override Task> QueryProcAsync(string procedureName, params DataParameter[] parameters)
{
//stored procedure is not support by SqLite
return Task.FromResult>(new List());
}
///
/// Executes SQL command and returns results as collection of values of specified type
///
/// Type of result items
/// SQL command text
/// Parameters to execute the SQL command
/// Collection of values of specified type
public override Task> QueryAsync(string sql, params DataParameter[] parameters)
{
using (new ReaderWriteLockDisposable(_locker, ReaderWriteLockType.Read))
return Task.FromResult>(DataContext.Query(sql, parameters).ToList());
}
///
/// Executes command asynchronously and returns number of affected records
///
/// Command text
/// Command parameters
/// Number of records, affected by command execution.
public override Task ExecuteNonQueryAsync(string sql, params DataParameter[] dataParameters)
{
using (new ReaderWriteLockDisposable(_locker, ReaderWriteLockType.Read))
{
using var dataConnection = CreateDataConnection(LinqToDbDataProvider);
var command = new CommandInfo(dataConnection, sql, dataParameters);
return command.ExecuteAsync();
}
}
///
/// Creates a new temporary storage and populate it using data from provided query
///
/// Name of temporary storage
/// Query to get records to populate created storage with initial data
/// Storage record mapping class
///
/// A task that represents the asynchronous operation
/// The task result contains the iQueryable instance of temporary storage
///
public override Task> CreateTempDataStorageAsync(string storeKey, IQueryable query)
{
return Task.FromResult>(new TempSqlDataStorage(storeKey, query, DataContext));
}
public Task DatabaseExistsAsync()
{
return Task.FromResult(DatabaseExists());
}
///
/// Truncates database table
///
/// Performs reset identity column
/// Entity type
public override Task TruncateAsync(bool resetIdentity = false)
{
using (new ReaderWriteLockDisposable(_locker))
DataContext.GetTable().Truncate(resetIdentity);
return Task.CompletedTask;
}
#endregion
#region Properties
protected DataConnection DataContext => _dataContext ??= CreateDataConnection();
///
/// Linq2Db data provider
///
protected override IDataProvider LinqToDbDataProvider { get; } = SQLiteTools.GetDataProvider(ProviderName.SQLiteMS);
///
/// Gets allowed a limit input value of the data for hashing functions, returns 0 if not limited
///
public int SupportedLengthOfBinaryHash { get; } = 0;
///
/// Gets a value indicating whether this data provider supports backup
///
public bool BackupSupported { get; } = false;
#endregion
}