public class PlainTextModel
{
[Required]
[Column("id")]
public string? ID { get; set; }
[Column("role")]
public string? Role { get; set; }
[Column("p_stat")]
public bool PStat { get; set; }
[Column("v_stat")]
public bool VStat { get; set; }
[Column("name")]
public string? Name { get; set; }
[Column("remarks")]
public string? Remarks { get; set; }
[Column("dt_registered")]
public string? DtRegistered { get; set; }
[Column("dt_modified")]
public string? DtModified { get; set; }
[Column("verified_by")]
public string? VerifiedBy { get; set; }
}
[Keyless]
public class ImageModel
{
[Column("img1")]
public byte[]? Image1 { get; set; }
[Column("img2")]
public byte[]? Image2 { get; set; }
[Column("img3")]
public byte[]? Image3 { get; set; }
}
< /code>
Конфигурации dbcontext: < /p>
using Microsoft.EntityFrameworkCore;
namespace MyProject.Data.SQLServer
{
public class SQLServerContext(DbContextOptions options) : DbContext(options)
{
public DbSet PlainTextModel { get; set; } = default!;
public DbSet ImageModel { get; set; } = default!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasNoKey();
modelBuilder.Entity()
.HasNoKey().ToView(null);
}
}
}
< /code>
Метод получения данных с открытым текстом: < /p>
public async Task PlainTextAsync(string spName, Dictionary parameters)
{
var paramDefs = SQLServerInnerHelper.GlobalMethodSPParam();
SqlParameter[] sqlParameter = MinimalDbSettings.SPArrayOfTuplesAndDict(paramDefs, parameters);
var sqlParam = MinimalDbSettings.SQLParamLessDynamic(spName, sqlParameter);
var result = await _context.PlainTextModel
.FromSql(sqlParam)
.ToListAsync();
return result.FirstOrDefault();
}
< /code>
Метод получения данных изображений: < /p>
public async Task ImageAsync(string spName, Dictionary parameters)
{
var paramDefs = SQLServerInnerHelper.GlobalMethodSPParam();
SqlParameter[] sqlParameter = MinimalDbSettings.SPArrayOfTuplesAndDict(paramDefs, parameters);
var sqlParam = MinimalDbSettings.SQLParamLessDynamic(spName, sqlParameter);
var result = await _context.ImageModel
.FromSql(sqlParam)
.ToListAsync();
return result.FirstOrDefault();
}
< /code>
Глобальный метод определения параметров (для гибкого извлечения параметров со страницы бритвы): < /p>
public static Dictionary GlobalMethodRazorPageParam(
object? id = null,
object? key = null,
object? spOutput = null) // for OUTPUT parameter, but I am not using it at the moment.
{
var pageParam = new Dictionary
{
["id"] = id,
["key"] = key,
["sp_output"] = spOutput
};
return pageParam;
}
< /code>
Глобальный метод определения параметра (для гибких параметров сохраненной процедуры SQL): < /p>
public static (string Name, SqlDbType Type, int? Size)[] GlobalMethodSPParam()
{
var paramDefs = new (string Name, SqlDbType Type, int? Size)[]
{
("id", SqlDbType.VarChar, 50),
("key", SqlDbType.VarChar, 100),
("sp_output", SqlDbType.NVarChar, 100),
};
return paramDefs;
}
< /code>
Глобальный метод для sqlParameter [] < /code> Определение: < /p>
public static SqlParameter[] SPArrayOfTuplesAndDict((string Name, SqlDbType Type, int? Size)[] paramDefs, Dictionary parameters)
{
var paramUpdatedValues = parameters.Values.ToList();
return [.. paramDefs
.Select((def, i) =>
{
var param = def.Size is null
? new SqlParameter(def.Name, def.Type)
: new SqlParameter(def.Name, def.Type, def.Size.Value);
if (def.Name == parameters.Keys.ToList()) {
param.Value = paramUpdatedValues ?? DBNull.Value;
} else {
throw new ArgumentException("Parameters misconfiguration found.");
}
return param;
})];
}
< /code>
Глобальный метод для formattablestring < /code> Определение: < /p>
public static FormattableString SQLParamLessDynamic(string spName, SqlParameter[] sqlParameters)
{
return sqlParameters.Length switch
{
// 0 => $"EXEC {storedProcedure}", // this isn't allowed here.
1 => $"EXEC {spName} {sqlParameters[0]}",
2 => $"EXEC {spName} {sqlParameters[0]}, {sqlParameters[1]}",
3 => $"EXEC {spName} {sqlParameters[0]}, {sqlParameters[1]}, {sqlParameters[2]}",
_ => throw new ArgumentException("Too many parameters provided."),
};
}
< /code>
backend /frontend < /h3>
Страница бритвы: < /p>
@page "/users/review-user"
@page "/users/review/{Id}/user"
@rendermode InteractiveServer
@using Microsoft.EntityFrameworkCore
@using MyProject.Models.SQLServer
@using MyProject.Data.SQLServer
@implements IAsyncDisposable
@inject IDbContextFactory DbFactory
@inject NavigationManager NavigationManager
Details
Review User
@if (plainTextModel is null)
{
Loading...
}
else
{
#
@rowNum
Role
@plainTextModel.Role
Display Name
@plainTextModel.Name
Remarks
@plainTextModel.Remarks
Date Registered
@plainTextModel.DtRegistered
Date Modified
@plainTextModel.DtModified
Verified By
@plainTextModel.VerifiedBy
@* other code here... *@
@if (imageModel is null)
{
Loading...
}
else
{
Image 1
@if (image1 is not null)
{
}
else
{
-
}
Image 2
@if (image2 is not null)
{
}
else
{
-
}
Image 3
@if (image3 is not null)
{
}
else
{
-
}
}
}
@code {
private PlainTextModel? plainTextModel = new();
private ImageModel? imageModel = new();
private SQLServerContext context = default!;
[SupplyParameterFromQuery(Name = "row")]
private long rowNum { get; set; }
[Parameter]
public string? Id { get; set; }
private string? image1;
private string? image2;
private string? image3;
protected override async Task OnInitializedAsync()
{
context = DbFactory.CreateDbContext();
await LoadPlainText();
await LoadImages();
}
private async Task LoadPlainText()
{
var sQLServerHelper = new SQLServerHelper(context);
var spParamPlainText = SQLServerInnerHelper.GlobalMethodRazorPageParam(id: Id, key:
"REVIEW_USER_PLAINTEXT");
plainTextModel = await sQLServerHelper.PlainTextAsync("myStoredProcedure", spParamPlainText);
// TODO: Let this load first.
if (plainTextModel is null)
{
NavigationManager.NavigateTo("notfound");
}
}
private async Task LoadImages()
{
var sQLServerHelper = new SQLServerHelper(context);
var spParamImage = SQLServerInnerHelper.GlobalMethodRazorPageParam(id: Id, key:
"REVIEW_USER_IMAGES");
imageModel = await sQLServerHelper.ImageAsync("myStoredProcedure",
spParamImage);
if (imageModel is null)
{
NavigationManager.NavigateTo("notfound");
}
image1 = dbDataToImg(imageModel?.Image1);
image2 = dbDataToImg(imageModel?.Image2);
image3 = dbDataToImg(imageModel?.Image3);
}
private string? dbDataToImg(byte[]? imgBytes)
{
if (imgBytes is null || imgBytes.Length == 0)
{
return null;
}
else
{
return $"data:image/png;base64,{Convert.ToBase64String(imgBytes)}";
}
}
public async ValueTask DisposeAsync() // this is important
{
await context.DisposeAsync();
}
}
< /code>
Я ожидал, что открытый текст будет отображаться первым перед изображениями, но это не было. < /p>
Подробнее здесь: https://stackoverflow.com/questions/797 ... -in-blazor
Мобильная версия