简体   繁体   中英

How to use Entity Framework Core in Blazor and Web API with one package

I want to build an app which provides web side (Blazor) and app side (Android, iOs, etc which use Web API communication). And I want to use EF Core to store my data.

The flow with Blazor and Web API is similar. So I want to use it with one package. Is there any way to Implement it?

The data tier sample, use DI

public class UserService : IUserService
{
    private SqlContext db;
    private IDbContextFactory<SqlContext> dbContextFactory;

    public UserService(SqlContext sqlContext, IDbContextFactory<SqlContext> dbContextFactory)
    {
        this.db = sqlContext;
        this.dbContextFactory = dbContextFactory;
    }

    public async Task Add(UserDTO userDTO, UserType Type)
    {
        var u = await db.Users.Where(u => u.Id == userDTO.Id).AsNoTracking().FirstOrDefaultAsync();

        if (u is not null)
        {
            throw new("same ID");
        }

        userDTO.Type = Type;
        var entity = userDTO.MapTo<UserEntity>();
        entity.Type = Type;

        await db.AddAsync(entity);
        await db.SaveChangesAsync();
    }

    public async Task UpdatePassword(string userId, string password)
    {
        var user = await db.Users
                           .SingleAsync(u => u.Id == userId);

        if (password != "")
        {
            user.Password = password.ToSHA512();
        }

        await db.SaveChangesAsync();
    }
}

It's working fine in Web API, but not in Blazor.

Blazor sample

@inject IUserService userService

<SpaceItem><Button Icon="@IconType.Outline.Redo" OnClick="()=>ResetPwd(context.Id)">resetPass</Button></SpaceItem>

    public async Task ResetPwd(string id)
    {
      var pwd = id.Substring(id.Length - 6);
      await userService.UpdatePassword(id, pwd);
    }

There is a problem, when I open the Blazor page, and use API to change password, then use Blazor reset password, the password which is in the response from the database is the last password.

https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-6.0

And I see dbcontextFactory, when I exec it, I need create every time. I need add one code in every func.

Is there any good way to get it?

First of all you shouldn't call service methods from blazor app. Blazor should communicate with service and DB through APIs. (You can use 'Refit' for maintaining API calls from blazor)

Maybe this is giving issue because you don't have SqlContext and DbContetFactory in blazor like in the API but this service expecting them as injection.

Firstly your UserService should look something like this using "unit of work" Db contexts - see this MS article for why - https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/#using-a-dbcontext-factory-eg-for-blazor

public class UserService : IUserService
{
    private IDbContextFactory<SqlContext> dbContextFactory;

    public UserService(IDbContextFactory<SqlContext> dbContextFactory)
    {
        this.dbContextFactory = dbContextFactory;
    }

    public async Task Add(UserDTO userDTO, UserType Type)
    {
        using db = this.dbContextFactory..CreateDbContext();
        //....
    }

    public async Task UpdatePassword(string userId, string password)
    {
        using db = this.dbContextFactory..CreateDbContext();
        //....
    }
}

You second issue is almost certainly a concurrency issue. It looks like you've alrady got the information in Blazor when you do the update through the API When do you actually get the user information in Blazor from the database? Without more information it's hard to be specific.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM