Camster
Camster
CC#
Created by Camster on 5/17/2024 in #help
EF Core Loses Decimal Precision After Save
I'm building a financial system for budgeting. All my money values in SQL server are stored as numeric(18, 2), which is correctly understood by EF Core. However, if I make a calculation that results in numbers beyond 2 decimal places and save it, EF Core does not automatically truncate the decimal value that was saved on the entity object. In the screenshot, I calculated a new value for "AmountPerMonth" and saved it via SaveChanges. After the save, the "Budget" entity object still has numbers beyond 2 decimal places. If I purge it and completely reload from DB, it loads only 2 decimal places, because obviously in the database it only saves 2. But I need it do truncate it after save, since I am trying to be efficient and automatically caching the value after save.
19 replies
CC#
Created by Camster on 4/18/2024 in #help
✅ IMemoryCache missing Contains?
No description
12 replies
CC#
Created by Camster on 2/29/2024 in #help
✅ MediatR Pipeline where TResponse has a generic type
All my API methods return a Result wrapper, like so:
public class Result
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public TimeSpan Time { get; set; }
public Exception ResultException { get; set; }
}

public class Result<T> : Result
{
public T Obj { get; set; }
}
public class Result
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public TimeSpan Time { get; set; }
public Exception ResultException { get; set; }
}

public class Result<T> : Result
{
public T Obj { get; set; }
}
3 replies
CC#
Created by Camster on 2/19/2024 in #help
MediatR in Class Library
I have an application that's broken up in 3 parts: API, Blazor, and Class Library. The Class Library contains all of the business logic. I want to start using the Notification pattern supplied by Mediatr to coordinate some of the more complex operations my application performs. However, I'm not sure how to instantiate or even use MediatR in a class library. All the examples on the internet show that you must register MediatR with the IServiceCollection. But my use of MediatR will be strictly within the Class Library, which does not have an IServiceCollection (I use a custom IFactory to manually inject inside the Class Library). I could of course use the one provided by the API and pass it into the Class Library, but after that, I'm not quite sure how the INotification implementations are supposed to be instantiated in the Class Library when they require injections that are internal to the Class Library and not exposed at all to the API.
22 replies
CC#
Created by Camster on 2/15/2024 in #help
EF Core Transaction in both SaveChanges and SqlQueryRaw for Unit Test
I have some complicated SQL script building that I need to unit test. The application uses data in EF that describes how the SQL should be built, and from that it builds a script to execute. I'm using xUnit database fixtures to build a database and seed it with data in a transaction. However, it appears that the transaction that's opened and being used by EF in SaveChanges it not being used by subsequent SqlQueryRaw call. The following unit test should return results, but it's not. It's possible there is a bug in the code I'm testing, but I've reviewed it several times and can't find it. My question is: can the transaction created from context.Database.BeginTransaction() be shared and used by context.Database.SqlQueryRaw?
public class ActionLoadTableFromHistoryTests : IClassFixture<DbFixture> {
public ActionLoadTableFromHistoryTests(DbFixture fixture)
=> Fixture = fixture;

private DbFixture Fixture { get; }

[Fact]
public async Task DoesLoadFromHistory_Load1() {

// Arrange
using var context = Fixture.CreateContext();
context.Database.BeginTransaction();
await SeedData.Perform(context);
await context.SaveChangesAsync();
context.ChangeTracker.Clear();

// Action
var action = new ActionLoadTableFromHistory(Actions.Get());
var historySql = await action.Perform(0, 1, false); // Uses data in EF to produce a SQL Script
var finalSql = $"{historySql.SelectSql} select * from {historySql.CurrentTableName} {historySql.CloseSql}";
var result = await context.Database.SqlQueryRaw<SourceTable>(finalSql, new object[0]).ToListAsync();

// Assert
Assert.NotNull(result);
Assert.NotEmpty(result);
}
}
public class ActionLoadTableFromHistoryTests : IClassFixture<DbFixture> {
public ActionLoadTableFromHistoryTests(DbFixture fixture)
=> Fixture = fixture;

private DbFixture Fixture { get; }

[Fact]
public async Task DoesLoadFromHistory_Load1() {

// Arrange
using var context = Fixture.CreateContext();
context.Database.BeginTransaction();
await SeedData.Perform(context);
await context.SaveChangesAsync();
context.ChangeTracker.Clear();

// Action
var action = new ActionLoadTableFromHistory(Actions.Get());
var historySql = await action.Perform(0, 1, false); // Uses data in EF to produce a SQL Script
var finalSql = $"{historySql.SelectSql} select * from {historySql.CurrentTableName} {historySql.CloseSql}";
var result = await context.Database.SqlQueryRaw<SourceTable>(finalSql, new object[0]).ToListAsync();

// Assert
Assert.NotNull(result);
Assert.NotEmpty(result);
}
}
3 replies
CC#
Created by Camster on 2/6/2024 in #help
Deploy Blazor Server and API to IIS in same website
No description
6 replies
CC#
Created by Camster on 1/25/2024 in #help
Generics without Casting
Is there any possible way to do what the code below is doing with generics, but without the casting?
public interface IItemCollection
{
int AddItem<T>(T item);
T GetItem<T>(int id);
}

public class ItemCollection : IItemCollection {
private Dictionary<Type, Dictionary<int, object>> _items = new();

public int AddItem<T>(T item)
{
var dictionary = GetDictionary<T>();
int next = dictionary.Keys.Max() + 1;
dictionary.Add(next, item);
return next;
}

public T GetItem<T>(int id)
{
var dictionary = GetDictionary<T>();
return (T)dictionary[id];
}

private Dictionary<int, object> GetDictionary<T>()
{
if (!_items.ContainsKey(typeof(T)))
_items.Add(typeof(T), new Dictionary<int, object>());
return _items[typeof(T)];
}
}
public interface IItemCollection
{
int AddItem<T>(T item);
T GetItem<T>(int id);
}

public class ItemCollection : IItemCollection {
private Dictionary<Type, Dictionary<int, object>> _items = new();

public int AddItem<T>(T item)
{
var dictionary = GetDictionary<T>();
int next = dictionary.Keys.Max() + 1;
dictionary.Add(next, item);
return next;
}

public T GetItem<T>(int id)
{
var dictionary = GetDictionary<T>();
return (T)dictionary[id];
}

private Dictionary<int, object> GetDictionary<T>()
{
if (!_items.ContainsKey(typeof(T)))
_items.Add(typeof(T), new Dictionary<int, object>());
return _items[typeof(T)];
}
}
20 replies
CC#
Created by Camster on 1/18/2024 in #help
SQL Sever: Changing getdate() to getutcdate()
This question is more related to SQL, but I wasn't sure where else to ask. Hope that's okay. I have a SQL Server in AEST/AEDT that has a table which has a default value of getdate() in a CreatedDate column of type DateTime. I want to change this to getutcdate(), and I want to change all the current date values for that column from their AEST/AEDT value to UTC. Of course, because they have Daylight Savings in Australia, this won't be easy. In fact, it may not be possible to be 100% accurate, but I think I can get close. Theoretically, I know that any date between 2am first Sunday in October and 3am first Sunday in April will be ADST, and anything else is AEST. Which means I can just run a dateadd for each year, like so:
--2022/2023 AEDT
update TableA
set CreatedDate = DATEADD(HOUR, -11, CreatedDate)
where CreatedDate between '2022-10-02 02:00:00.000' and '2023-04-02 02:59:59.999'

--2023 AEST
update TableA
set CreatedDate = DATEADD(HOUR, -10, CreatedDate)
where CreatedDate between '2023-04-02 03:00:00.000' and '2023-10-01 01:59:59.999'
--2022/2023 AEDT
update TableA
set CreatedDate = DATEADD(HOUR, -11, CreatedDate)
where CreatedDate between '2022-10-02 02:00:00.000' and '2023-04-02 02:59:59.999'

--2023 AEST
update TableA
set CreatedDate = DATEADD(HOUR, -10, CreatedDate)
where CreatedDate between '2023-04-02 03:00:00.000' and '2023-10-01 01:59:59.999'
The only problem is that for any dates between 2am and 3am on 2023-04-02, it's impossible to know if they occurred in AEST or AEDT. But I'm honestly not worried about it; I don't need to be 100% accurate. I just wanted to make sure there isn't something I'm not thinking of. Maybe someone else has had to do this before? I couldn't find anything in google. Any help would be appreciated, thank you!
5 replies
CC#
Created by Camster on 10/10/2023 in #help
❔ Invalid 'nullable' value in Visual Studio
No description
15 replies
CC#
Created by Camster on 10/6/2023 in #help
❔ NSwag and API help
I'm learning how to build an APIs and connect to it from a Blazor front-end. I'm using NSwag to build the http service client. I suppose this might be an NSwag question more than C#, but perhaps I'm just doing it completely wrong. In my API, all my function calls are wrapped in a custom Result class:
public class Result
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public string Error { get; set; }
}

public class Result<T> : Result
{
public T Obj { get; set; }
}
public class Result
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public string Error { get; set; }
}

public class Result<T> : Result
{
public T Obj { get; set; }
}
So an example call in the API would be:
public interface IAPICaller
{
Task<Result<AccountEntity>> Account_Create(AccountCreateDTO create);
Task<Result<List<AccountEntity>>> Account_Get(bool showInactive);
Task<Result<AccountEntity>> Account_Update(AccountUpdateDTO update);
}
public interface IAPICaller
{
Task<Result<AccountEntity>> Account_Create(AccountCreateDTO create);
Task<Result<List<AccountEntity>>> Account_Get(bool showInactive);
Task<Result<AccountEntity>> Account_Update(AccountUpdateDTO update);
}
The problem is that NSwag flattens the call into one class:
public partial interface IClient
{
System.Threading.Tasks.Task<AccountEntityListResult> AccountsGetAsync(bool showInactive)
}

public partial class AccountEntityListResult
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public string Error { get; set; }
public System.Collections.Generic.ICollection<AccountEntity> Obj { get; set; }
}
public partial interface IClient
{
System.Threading.Tasks.Task<AccountEntityListResult> AccountsGetAsync(bool showInactive)
}

public partial class AccountEntityListResult
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public string Error { get; set; }
public System.Collections.Generic.ICollection<AccountEntity> Obj { get; set; }
}
How can I get NSwag to build the classes to be separated like they are in the API? My plan is to build generic functions in the front-end to depend on the Result class, with different logic based on the IsSuccess, Message, and Error properties. Thank you for your help!
3 replies
CC#
Created by Camster on 9/14/2023 in #help
❔ Blazor State Container Prompt, Standardized for all Pages
I have a simple state container in blazor. The goal is to provide the AppEntity value:
public class StateContainer {
public AppEntity App { get; set; }
public event Action OnStateChange;
public void SetApp(AppEntity app) {
App = app;
NotifyStateChanged();
}

private void NotifyStateChanged() => OnStateChange?.Invoke();
}
public class StateContainer {
public AppEntity App { get; set; }
public event Action OnStateChange;
public void SetApp(AppEntity app) {
App = app;
NotifyStateChanged();
}

private void NotifyStateChanged() => OnStateChange?.Invoke();
}
The container is injected in the services collection.
builder.Services.AddSingleton<StateContainer>();
builder.Services.AddSingleton<StateContainer>();
I have a component which provides the user a selection dropdown to set the AppEntity in the State Container. Subsequent pages inject the State Container and use it if needed. My question is: if for some reason a page that requires the State Container has a null value for AppEntity (e.g., user navigated to a specific page by url, bypassing the selection page), how can I have a generic popup prompt that prompts the user for the selection? Ideally, I'd want to minimize the code in any page that needs it as much as possible. The only way I can think to do this is to build the prompt in a base component and inherit from it, but perhaps there might be a simpler or more elegant way.
5 replies
CC#
Created by Camster on 8/17/2023 in #help
✅ EF Core, Proper DbContext Instantiation
When instantiating the DbContext, I've always created it in a Repository class (not a generic repository, rather a unit of work repository). First I extend the DbContext to allow construction via connection string, like so.
public partial class MyContext {
public MyContext (string connectionString) : base(GetOptions(connectionString)) { }

private static DbContextOptions GetOptions(string connectionString) {
return SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), connectionString).Options;
}
}
public partial class MyContext {
public MyContext (string connectionString) : base(GetOptions(connectionString)) { }

private static DbContextOptions GetOptions(string connectionString) {
return SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), connectionString).Options;
}
}
Then in the Repository class, I instantiate it like so:
public class Repository {
private string _connectionString;

public Repository(string connectionString) {
_connectionString = connectionString;
}

public async Task<List<Entity_DTO>> Update_Entity(List<UpdateEntity_DTO> update) {
using (var context = new MyContext(_connectionString)) {
// Perform Update
await context.SaveChangesAsync();
return await GetEntityList();
}
}
}
public class Repository {
private string _connectionString;

public Repository(string connectionString) {
_connectionString = connectionString;
}

public async Task<List<Entity_DTO>> Update_Entity(List<UpdateEntity_DTO> update) {
using (var context = new MyContext(_connectionString)) {
// Perform Update
await context.SaveChangesAsync();
return await GetEntityList();
}
}
}
This works fine for me, but I've seen a lot of examples where the DbContext is injected in the front-end. Hence, it is never instantiated. My question is, what are the reasons for this? Is it really advantageous to inject the DbContext? Is the way I do it an absolute no-no?
6 replies
CC#
Created by Camster on 8/16/2023 in #help
❔ Thin/Thick UI Design
Hi! I've been a longtime c#.net programmer at a corporate office. I've been wanting to do some side work though, and I would love for it to grow to fulltime freelance. Problem is that most of my work has been intranet applications that are functionally sound but not very pretty. I've always considered myself a developer of systems with web interfaces, rather than a true web developer. My front-end experience is WinForms, ASP.NET MVC, and Blazor. Is it worth learning the popular frameworks like WPF and React? Any resources out there on how to make web/apps that look pretty and good UI design? Appreciate the help 🙂
19 replies
CC#
Created by Camster on 8/8/2023 in #help
❔ Blazor Cascading Parameter with Async Change Event
Hi! I have a working cascading parameter, where the child component has a CascadingParameter property. It works just fine, when the parent changes the value, the value is propagated to the child. The difficulty I'm having is that I want the child component to do some async server work when that value changes. Think of it as a cascading drop down - the parent has a drop down, and when a value is selected, the child component needs to go to the server to get data to fill a child drop down. I'm just not sure how to do that. The child component obviously has a get/set event on the cascading value, but I don't think you can do an async call from the set event. I've tried to do some googling, but everything I find talks about how to propagate values up the chain via EventCallback, which is the reverse of what I need to do. Thank you for your help!
10 replies
CC#
Created by Camster on 7/14/2023 in #help
❔ ✅ Use Reflection or Generics to specify one or more properties
I'm writing something that will automatically create a table and fill it with data based on the properties of a generic object. It's for unit testing, to be built and blown away when finished, so I don't need a heavy-duty framework like EF Core. Hopefully the code below makes sense, without all the details. I'm just looping through the properties and building Create Table and Insert sql statements.
public class Table<T> {
public string GetSql_CreateTable() {
var sql = new StringBuilder();
foreach (var prop in typeof(T).GetProperties()) {
// generate create table sql
}
return sql.ToString();
}

public string Fill(List<T> rows) {
var sql = new StringBuilder();
// generate insert sql
return sql.ToString();
}
}
public class Table<T> {
public string GetSql_CreateTable() {
var sql = new StringBuilder();
foreach (var prop in typeof(T).GetProperties()) {
// generate create table sql
}
return sql.ToString();
}

public string Fill(List<T> rows) {
var sql = new StringBuilder();
// generate insert sql
return sql.ToString();
}
}
Where I'm stuck is how to specify one or more properties of the generic object to be part of a primary key. I'm not sure syntatically how to say, "use these properties for primary key". Any help would be appreciated!
8 replies