Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ysmoradi committed Nov 18, 2024
1 parent aa3c04b commit 6be411d
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,6 @@
</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<PropertyGroup Condition=" ('$(offlineDb)' == 'true' OR '$(offlineDb)' == '') AND ('$(framework)' == 'net9.0' OR '$(framework)' == '')">
<!--/-:msbuild-conditional:noEmit -->
<!-- Add Microsoft.EntityFrameworkCore.Tasks package to make automated db context optimize work -->
<EFOptimizeContext Condition="'$(Configuration)'=='Release'">true</EFOptimizeContext>
<DbContextName>OfflineDbContext</DbContextName>
<EFStartupProject>..\..\Server\Boilerplate.Server.Web\Boilerplate.Server.Web.csproj</EFStartupProject>
<!--/+:msbuild-conditional:noEmit -->
</PropertyGroup>

<ItemGroup>
<SupportedPlatform Include="browser" />

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// <auto-generated />
using Boilerplate.Client.Core.Data;
using Microsoft.EntityFrameworkCore.Infrastructure;

#pragma warning disable 219, 612, 618
#nullable disable

[assembly: DbContextModel(typeof(OfflineDbContext), typeof(OfflineDbContextModel))]
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Boilerplate.Client.Core.Data
{
[DbContext(typeof(OfflineDbContext))]
public partial class OfflineDbContextModel : RuntimeModel
{
private static readonly bool _useOldBehavior31751 =
System.AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31751", out var enabled31751) && enabled31751;

static OfflineDbContextModel()
{
var model = new OfflineDbContextModel();

if (_useOldBehavior31751)
{
model.Initialize();
}
else
{
var thread = new System.Threading.Thread(RunInitialization, 10 * 1024 * 1024);
thread.Start();
thread.Join();

void RunInitialization()
{
model.Initialize();
}
}

model.Customize();
_instance = (OfflineDbContextModel)model.FinalizeModel();
}

private static OfflineDbContextModel _instance;
public static IModel Instance => _instance;

partial void Initialize();

partial void Customize();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Boilerplate.Client.Core.Data
{
public partial class OfflineDbContextModel
{
private OfflineDbContextModel()
: base(skipDetectChanges: false, modelId: new Guid("b97b95bd-89b9-4be0-a574-d2035391c0c8"), entityTypeCount: 1)
{
}

partial void Initialize()
{
var userDto = UserDtoEntityType.Create(this);

UserDtoEntityType.CreateAnnotations(userDto);

AddAnnotation("ProductVersion", "9.0.0");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// <auto-generated />
using System;
using System.Reflection;
using Boilerplate.Shared.Dtos.Identity;
using Boilerplate.Shared.Enums;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Boilerplate.Client.Core.Data
{
[EntityFrameworkInternal]
public partial class UserDtoEntityType
{
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
{
var runtimeEntityType = model.AddEntityType(
"Boilerplate.Shared.Dtos.Identity.UserDto",
typeof(UserDto),
baseEntityType,
propertyCount: 9,
keyCount: 1);

var id = runtimeEntityType.AddProperty(
"Id",
typeof(Guid),
propertyInfo: typeof(UserDto).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
valueGenerated: ValueGenerated.OnAdd,
afterSaveBehavior: PropertySaveBehavior.Throw,
sentinel: new Guid("00000000-0000-0000-0000-000000000000"));

var birthDate = runtimeEntityType.AddProperty(
"BirthDate",
typeof(DateTimeOffset?),
propertyInfo: typeof(UserDto).GetProperty("BirthDate", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<BirthDate>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
nullable: true,
valueConverter: new DateTimeOffsetToBinaryConverter());

var email = runtimeEntityType.AddProperty(
"Email",
typeof(string),
propertyInfo: typeof(UserDto).GetProperty("Email", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<Email>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
nullable: true);

var fullName = runtimeEntityType.AddProperty(
"FullName",
typeof(string),
propertyInfo: typeof(UserDto).GetProperty("FullName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<FullName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));

var gender = runtimeEntityType.AddProperty(
"Gender",
typeof(Gender?),
propertyInfo: typeof(UserDto).GetProperty("Gender", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<Gender>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
nullable: true);

var password = runtimeEntityType.AddProperty(
"Password",
typeof(string),
propertyInfo: typeof(UserDto).GetProperty("Password", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<Password>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));

var phoneNumber = runtimeEntityType.AddProperty(
"PhoneNumber",
typeof(string),
propertyInfo: typeof(UserDto).GetProperty("PhoneNumber", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<PhoneNumber>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
nullable: true);

var profileImageName = runtimeEntityType.AddProperty(
"ProfileImageName",
typeof(string),
propertyInfo: typeof(UserDto).GetProperty("ProfileImageName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<ProfileImageName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
nullable: true);

var userName = runtimeEntityType.AddProperty(
"UserName",
typeof(string),
propertyInfo: typeof(UserDto).GetProperty("UserName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(UserDto).GetField("<UserName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));

var key = runtimeEntityType.AddKey(
new[] { id });
runtimeEntityType.SetPrimaryKey(key);

return runtimeEntityType;
}

public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
{
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
runtimeEntityType.AddAnnotation("Relational:Schema", null);
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
runtimeEntityType.AddAnnotation("Relational:TableName", "Users");
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);

Customize(runtimeEntityType);
}

static partial void Customize(RuntimeEntityType runtimeEntityType);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
using Boilerplate.Shared.Dtos.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.Options;

namespace Boilerplate.Client.Core.Data;

public partial class OfflineDbContext(DbContextOptions<OfflineDbContext> options) : DbContext(options)
public partial class OfflineDbContext : DbContext
{
static OfflineDbContext()
{
if (AppPlatform.IsBrowser)
{
AppContext.SetSwitch("Microsoft.EntityFrameworkCore.Issue31751", true);
}
}

public virtual DbSet<UserDto> Users { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
Expand All @@ -40,4 +33,31 @@ protected override void ConfigureConventions(ModelConfigurationBuilder configura
configurationBuilder.Properties<DateTimeOffset>().HaveConversion<DateTimeOffsetToBinaryConverter>();
configurationBuilder.Properties<DateTimeOffset?>().HaveConversion<DateTimeOffsetToBinaryConverter>();
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var isRunningInsideDocker = Directory.Exists("/container_volume"); // Blazor Server - Docker (It's supposed to be a mounted volume named /container_volume)
var dirPath = isRunningInsideDocker ? "/container_volume"
: AppPlatform.IsBlazorHybridOrBrowser ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AC87AA5B-4B37-4E52-8468-2D5DF24AF256")
: Directory.GetCurrentDirectory(); // Blazor server (Non docker Linux, macOS or Windows)

dirPath = Path.Combine(dirPath, "App_Data");

Directory.CreateDirectory(dirPath);

var dbPath = Path.Combine(dirPath, "Offline.db");

optionsBuilder
.UseSqlite($"Data Source={dbPath}");

if (AppEnvironment.IsProd())
{
optionsBuilder.UseModel(OfflineDbContextModel.Instance);
}

optionsBuilder.EnableSensitiveDataLogging(AppEnvironment.IsDev())
.EnableDetailedErrors(AppEnvironment.IsDev());

base.OnConfiguring(optionsBuilder);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
## bit entity framework core sqlite (bit Besql)
## bit entity framework core sqlite (bit Besql)

How to use `Bit.Besql`:

The usage of `Bit.Besql` is exactly the same as the regular usage of `Microsoft.EntityFrameworkCore.Sqlite` with [IDbContextFactory](https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-ef-core?view=aspnetcore-8.0#new-dbcontext-instances).

To get start, simply install `Bit.Besql` and use `services.AddBesqlDbContextFactory` instead of `services.AddDbContextFactory`.

In order to download sqlite db file from browser cache storage in blazor WebAssembly run the followings in browser console:
```js
const cache = await caches.open('Bit-Besql');
Expand All @@ -16,11 +14,11 @@ URL.createObjectURL(blob);

**Migration**

Set `Server` as the Startup Project in solution explorer and set `Client.Core` it as the Default Project in Package Manager Console and run the following commands:
Set `Server.Web` as the Startup Project in solution explorer and set `Client.Core` it as the Default Project in Package Manager Console and run the following commands:
```powershell
Add-Migration InitialMigration -OutputDir Data\Migrations -Context OfflineDbContext
```
Or open a terminal in your Server project directory and run followings:
Or open a terminal in your Server.Web project directory and run followings:
```bash
dotnet ef migrations add InitialMigration --context OfflineDbContext --output-dir Data/Migrations --project ../Client/Boilerplate.Client.Core/Boilerplate.Client.Core.csproj
```
Expand All @@ -35,18 +33,12 @@ To enhance the performance of your models, consider compiling them using EF Core

To implement this optimization, follow these steps in the Package Manager Console:

1. Make sure `Boilerplate.Server` is set as the default startup project, and `Boilerplate.Client.Core` is the default project in the Package Manager Console.
1. Make sure `Server.Web` is set as the default startup project, and `Client.Core` is the default project in the Package Manager Console.

2. Run the following command:

```powershell
Optimize-DbContext -Context OfflineDbContext -OutputDir Data/CompiledModel -Namespace Boilerplate.Client.Core.Data
```
3. Uncomment the following line in the `Boilerplate.Client.Core/Extensions/IServiceCollectionExtensions.cs` file:
```csharp
.UseModel(OfflineDbContextModel.Instance)
```
By adhering to these steps, you leverage EF Core compiled models to boost the performance of your application, ensuring an optimized and efficient data access method.
Original file line number Diff line number Diff line change
Expand Up @@ -78,26 +78,11 @@ public static IServiceCollection AddClientCoreProjectServices(this IServiceColle
});

//#if (offlineDb == true)
services.AddBesqlDbContextFactory<OfflineDbContext>(options =>
if (AppPlatform.IsBrowser)
{
var isRunningInsideDocker = Directory.Exists("/container_volume"); // Blazor Server - Docker (It's supposed to be a mounted volume named /container_volume)
var dirPath = isRunningInsideDocker ? "/container_volume"
: AppPlatform.IsBlazorHybridOrBrowser ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AC87AA5B-4B37-4E52-8468-2D5DF24AF256")
: Directory.GetCurrentDirectory(); // Blazor server (Non docker Linux, macOS or Windows)

dirPath = Path.Combine(dirPath, "App_Data");

Directory.CreateDirectory(dirPath);

var dbPath = Path.Combine(dirPath, "Offline.db");

options
// .UseModel(OfflineDbContextModel.Instance)
.UseSqlite($"Data Source={dbPath}");

options.EnableSensitiveDataLogging(AppEnvironment.IsDev())
.EnableDetailedErrors(AppEnvironment.IsDev());
});
AppContext.SetSwitch("Microsoft.EntityFrameworkCore.Issue31751", true);
}
services.AddBesqlDbContextFactory<OfflineDbContext>();
//#endif

//#if (appInsights == true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private void App_DispatcherUnhandledException(object sender, System.Windows.Thre
{
var errorMessage = e.Exception.ToString();
System.Windows.Clipboard.SetText(errorMessage);
System.Windows.Forms.MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Windows.MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}

e.Handled = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<RootNamespace>Boilerplate.Client.Windows</RootNamespace>
<StartupObject>Boilerplate.Client.Windows.Program</StartupObject>
Expand Down Expand Up @@ -36,9 +35,6 @@
<PackageReference Include="Velopack" />
<!--/+:msbuild-conditional:noEmit -->
<PackageReference Condition="'$(sample)' == 'Admin' OR '$(sample)' == ''" Include="Newtonsoft.Json" />
<PackageReference Condition=" '$(appCenter)' == 'true' OR '$(appCenter)' == '' " Include="Microsoft.AppCenter.Analytics" />
<PackageReference Condition=" '$(appCenter)' == 'true' OR '$(appCenter)' == '' " Include="Microsoft.AppCenter.Crashes" />
<PackageReference Condition=" '$(appCenter)' == 'true' OR '$(appCenter)' == '' " Include="West.Extensions.Logging.AppCenter" />
<PackageReference Condition=" '$(appInsights)' == 'true' OR '$(appInsights)' == '' " Include="Microsoft.Extensions.Logging.ApplicationInsights" />
<!--/-:msbuild-conditional:noEmit -->
<Content Include="..\Boilerplate.Client.Maui\wwwroot\index.html" Link="wwwroot\index.html">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//+:cnd:noEmit
using Microsoft.Web.WebView2.Core;
using Microsoft.AspNetCore.Components.WebView;
using System.Drawing;
using System.Diagnostics;

namespace Boilerplate.Client.Windows;

Expand Down Expand Up @@ -30,8 +32,9 @@ public MainWindow()
}
AppWebView.Services.GetRequiredService<PubSubService>().Subscribe(ClientPubSubMessages.CULTURE_CHANGED, async culture =>
{
string executablePath = Environment.ProcessPath!;
Process.Start(executablePath);
App.Current.Shutdown();
Application.Restart();
});
AppWebView.Loaded += async delegate
{
Expand Down
Loading

0 comments on commit 6be411d

Please sign in to comment.