Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CS/PivotTableBindToData/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
@using Microsoft.EntityFrameworkCore
@using DevExpress.Data.Linq
@inject IDbContextFactory<SalesContext> SalesContextFactory
@inject IConfiguration Configuration
@implements IAsyncDisposable
@using DevExpress.Blazor.PivotTable

Expand All @@ -26,13 +25,16 @@
}
else if (DataExists == false) {
<div class="generate-data-container">
<p>The Sales table (or the database file) was not found.</p>
<p>The Sales table was not found.</p>
<DxButton Text="Generate data" Enabled="@(!IsGenerating)" Click="@GenerateDataAsync" />
@if (IsGenerating) {
<p>Generating 1,000,000 rows, please wait...</p>
}
</div>
}
else {
<p>Checking for data...</p>
}

@code {
SalesContext SalesContext { get; set; }
Expand All @@ -58,7 +60,7 @@ else if (DataExists == false) {
IsGenerating = true;
StateHasChanged();

await Task.Run(() => SalesDataGenerator.GenerateAsync(SalesContext, Configuration.GetValue("DataProvider", DataProviders.SQLite.ToString())));
await Task.Run(() => SalesDataGenerator.GenerateAsync(SalesContext));

CreateDataSource();
DataExists = true;
Expand Down
6 changes: 3 additions & 3 deletions CS/PivotTableBindToData/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
builder.Services.AddDevExpressBlazor();


var dataProviderSetting = builder.Configuration.GetValue("DataProvider", DataProviders.SQLite.ToString());
var dataProvider = builder.Configuration.GetValue("DataProvider", DataProviders.SQLite);

if (dataProviderSetting == DataProviders.SQLite.ToString()) {
if (dataProvider == DataProviders.SQLite) {
builder.Services.AddDbContextFactory<SalesContext>((sp, options) => {
var env = sp.GetRequiredService<IWebHostEnvironment>();
var dbPath = Path.Combine(env.ContentRootPath, "sales.db");
options.UseSqlite("Data Source=" + dbPath);
});
}
else if (dataProviderSetting == DataProviders.SqlServer.ToString()) {
else if (dataProvider == DataProviders.SqlServer) {
builder.Services.AddDbContextFactory<SalesContext>(options => {
options.UseSqlServer(builder.Configuration.GetConnectionString("SalesDatabase"));
});
Expand Down
12 changes: 11 additions & 1 deletion CS/PivotTableBindToData/SalesDb/DataProviders.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
namespace PivotTableBindToData.SalesDb {
using System;

namespace PivotTableBindToData.SalesDb {
public enum DataProviders {
SQLite,
SqlServer
}

public static class DataProvidersExtensions {
public static DataProviders FromEFProviderName(string efProviderName) => efProviderName switch {
"Microsoft.EntityFrameworkCore.Sqlite" => DataProviders.SQLite,
"Microsoft.EntityFrameworkCore.SqlServer" => DataProviders.SqlServer,
_ => throw new NotSupportedException($"Unsupported database provider: '{efProviderName}'.")
};
}
}
66 changes: 51 additions & 15 deletions CS/PivotTableBindToData/SalesDb/SalesDataGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;

#nullable disable
Expand All @@ -8,34 +9,69 @@ namespace PivotTableBindToData.SalesDb {
public static class SalesDataGenerator {

public static async Task<bool> SalesTableExistsAsync(SalesContext context) {
try {
await context.Sales.Select(s => s.SaleId).Take(1).ToListAsync();
return true;
}
catch {
if (!await DatabaseExistsAsync(context))
return false;
}
return await SalesTableExistsInDatabaseAsync(context);
}
Comment thread
Schullz marked this conversation as resolved.

static async Task<bool> DatabaseExistsAsync(SalesContext context) {
return await context.Database.CanConnectAsync();
}

static async Task<bool> SalesTableExistsInDatabaseAsync(SalesContext context) {
string sql = GetDataProvider(context) switch {
DataProviders.SQLite =>
"SELECT count(*) AS [Value] FROM sqlite_master WHERE type = 'table' AND name = 'Sales'",
DataProviders.SqlServer =>
"SELECT count(*) AS [Value] FROM sys.tables WHERE name = 'Sales'",
var provider => throw new NotSupportedException($"Unsupported database provider: '{provider}'.")
};

int tableCount = await context.Database.SqlQueryRaw<int>(sql).SingleAsync();
return tableCount > 0;
}

public static async Task GenerateAsync(SalesContext context, string dataProvider) {
public static async Task GenerateAsync(SalesContext context) {
var dataProvider = GetDataProvider(context);
string resourceName = dataProvider switch {
nameof(DataProviders.SQLite) => "PivotTableBindToData.SalesDb.Scripts.SQLiteDbGenerator.sql",
nameof(DataProviders.SqlServer) => "PivotTableBindToData.SalesDb.Scripts.SqlServerDbGenerator.sql",
DataProviders.SQLite => "PivotTableBindToData.SalesDb.Scripts.SQLiteDbGenerator.sql",
DataProviders.SqlServer => "PivotTableBindToData.SalesDb.Scripts.SqlServerDbGenerator.sql",
_ => ""
};

string script = await ReadEmbeddedScriptAsync(resourceName);

var batches = Regex.Split(script, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase)
.Select(batch => batch.Trim())
.Where(batch => batch.Length > 0);

context.Database.SetCommandTimeout(0);
if (dataProvider == DataProviders.SqlServer) {
var connectionStringBuilder = new SqlConnectionStringBuilder(context.Database.GetConnectionString());
string databaseName = connectionStringBuilder.InitialCatalog;
script = script.Replace("{DatabaseName}", databaseName);
connectionStringBuilder.InitialCatalog = "master";

await using var connection = new SqlConnection(connectionStringBuilder.ConnectionString);
await connection.OpenAsync();

foreach (var batch in batches)
await context.Database.ExecuteSqlRawAsync(batch);
var batches = Regex.Split(script, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase)
.Select(batch => batch.Trim())
.Where(batch => batch.Length > 0)
.ToList();

foreach (var batch in batches) {
await using var command = connection.CreateCommand();
command.CommandText = batch;
command.CommandTimeout = 0;
await command.ExecuteNonQueryAsync();
}
return;
}

context.Database.SetCommandTimeout(0);
await context.Database.ExecuteSqlRawAsync(script);
}

static DataProviders GetDataProvider(SalesContext context) =>
DataProvidersExtensions.FromEFProviderName(context.Database.ProviderName);
Comment thread
Schullz marked this conversation as resolved.

static async Task<string> ReadEmbeddedScriptAsync(string resourceName) {
var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream(resourceName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
USE [master];
GO

IF DB_ID(N'{DatabaseName}') IS NULL
BEGIN
CREATE DATABASE [{DatabaseName}];
END
GO

USE [{DatabaseName}];
GO
Comment thread
Schullz marked this conversation as resolved.

IF OBJECT_ID('dbo.Sales', 'U') IS NOT NULL
DROP TABLE dbo.Sales;
GO
Expand Down
2 changes: 1 addition & 1 deletion CS/PivotTableBindToData/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"DataProvider": "SQLite", // SQLite or SqlServer
"ConnectionStrings": {
"SalesDatabase": "Server=(localdb)\\MSSQLLocalDB;Database=Example;Trusted_Connection=True;"
"SalesDatabase": "Server=(localdb)\\MSSQLLocalDB;Database=DevExpressPivotTableDb;Trusted_Connection=True;"
},
"Logging": {
"LogLevel": {
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<!-- default badges end -->
# Blazor Pivot Table – Data binding using Entity Framework Core in Server Mode

This example uses [Entity Framework Core](https://learn.microsoft.com/en-us/ef/core/) to bind the [DevExpress Blazor Pivot Table](https://docs.devexpress.com/Blazor/405245/components/pivot-table) to data in Server Mode. This example supports SQLite and SQL Server. The database engine is sonfigured in the `appsettings.json` file.
This example uses [Entity Framework Core](https://learn.microsoft.com/en-us/ef/core/) to bind the [DevExpress Blazor Pivot Table](https://docs.devexpress.com/Blazor/405245/components/pivot-table) to data in Server Mode. This example supports SQLite and SQL Server. The database engine is configured in the `appsettings.json` file.
Comment thread
Schullz marked this conversation as resolved.

![Bind DevExpress Blazor Pivot Table to Data with Entity Framework Core](/images/bind-to-data.png)

Expand Down
Loading