How to connect Blazor WebAssembly to DataBase
I recently started developing a Blazor WebAssembly app, and now I'm settling on a database connection.
All lessons and instructions say that you need to enter information into the Startup.cs file and appsettings.json, but these files are not in the project.
I do not understand. In Blazor WebAssembly, is there no way to connect to the DB?
Solution 1:
Not directly. Blazor WebAssembly is a front end framework. You need to create an API controller to wrap your database connection and use HttpClient to call the api. A straight forward way to do it is to use an asp.net core web api controller wrapping an Entity Framework Core Database context.
@inject HttpClient Http
<template_html_here/>
@code
{
protected override async Task OnInitializedAsync()
{
products = await Http.GetFromJsonAsync<Product[]>("api/Products");
}
}
Controller:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly ProductsDbContext _context; // your database context
public ProductsController(ProductsDbContext context)
{
_context = context;
}
[HttpGet]
public IEnumerable<Product> Get()
{
return _context.Products.ToList();
}
}
You can read more about blazor at https://docs.microsoft.com/en-us/aspnet/core/blazor/call-web-api?view=aspnetcore-3.1. And on asp.net core web APIs on https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.1&tabs=visual-studio.
Solution 2:
If you are referring to local storage (browser storage) then this component by Chris Sainty could help you.
However if you are looking for a connection to a Database like a SQL Server or document storage like Mongo it can not be done directly.
Blazor Wasm is for front end development. You will need to call web APIs that connect to databases stored on servers.
Solution 3:
It is now 2022. .NET 6 has shipped, and Blazor WebAssembly has support for compiled binaries.
That means there are now three options for using a database in a Blazor WebAssembly application.
#1. Create a webApi. Call the webApi on from the client as you can see being done in the default sample. See FetchData.razor
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
}
and WeatherForecastController.cs on the server. The default solution does not call a database, but you could easily use a dbContext in Get() to pull data from a database.
#2: With support for compiled binaries in Blazor WebAssembly, it is now possible to completely host Sqlite in WebAssembly.
https://github.com/TrevorDArcyEvans/BlazorSQLiteWasm
#3: IndexedDb. Through js interop, the IndexDb in the browser can be used. Large amounts of data can be stored in this Db, and like the name implies, it is indexed. Since this can be accidentally cleared, it is most useful in a PWA, where that is more difficult. Also, with this and Sqlite, anything done in the browser is open to the user and hackers that compromise the user's maching.
I use https://github.com/wtulloch/Blazor.IndexedDB
You add schema in program.cs:
builder.Services.AddIndexedDB(dbStore =>
{
dbStore.DbName = "SomeDbName";
dbStore.Version = 1;
dbStore.Stores.Add(new StoreSchema
{
Name = "People",
PrimaryKey = new IndexSpec { Name = "id", KeyPath = "id", Auto = false },
Indexes = new List<IndexSpec>
{
new IndexSpec{Name="alias", KeyPath = "alias", Auto=false},
new IndexSpec{Name="isAvailable", KeyPath = "isAvailable", Auto=false},
new IndexSpec{Name="communityId", KeyPath = "communityId", Auto=false},
new IndexSpec{Name="isFriend", KeyPath = "isFriend", Auto=false},
}
});
});
In this code, the names of the fields are camelCased, whereas the objects I'm constructing are PascalCase. This was actually necessary for me to get it to work. I think my serializer may be set to camelCase Json or something, so watch that.
And then you add remove and search using:
public async Task AddPersonAsync(LocalPerson member)
{
var newPerson = new StoreRecord<LocalPerson>
{
Data = member,
Storename = PeopleStoreName
};
await _dbManager.AddRecord(newPerson);
}
public async Task<LocalPerson> GetPersonByIdAsync(Guid id)
{
var localPerson = await _dbManager.GetRecordById<Guid, LocalPerson>(PeopleStoreName, id);
return localPerson;
}
public async Task<List<LocalPerson>> GetPeopleAsync()
{
var results = await _dbManager.GetRecords<LocalPerson>(PeopleStoreName);
return results;
}
public async Task<List<LocalPerson>> GetPeopleByCommunityAsync(Guid id)
{
var indexSearch = new StoreIndexQuery<Guid>
{
Storename = PeopleStoreName,
IndexName = "communityId",
QueryValue = id,
};
var result = await _dbManager.GetAllRecordsByIndex<Guid, LocalPerson>(indexSearch);
if (result is null)
{
return new List<LocalPerson>();
}
return (List<LocalPerson>)result;
}