![](/img/trans.png)
[英]Updating a SQLite Database to reflect a change to the model with Entity Framework Core and .NET 6
[英]Entity Framework (EF) and .Net 6 Blazor not updating database
我需要帮助试图了解为什么我的 .net Core 6 中的 Blazor(服务器端)组件在删除实体时没有更新我的数据库,请查看我的代码示例:(事先,感谢您的所有帮助!)
首先,我按如下方式注入我的数据库上下文:
@inject AppDbContext db
然后,在我的代码下面,我决定查询一些数据,在这种情况下,客户如下:
@code {
private List<Customer> clients { get; set; }
protected override async Task OnInitializedAsync()
{
clients = await db.Customers.ToListAsync();
}
}
现在,我创建了一个带有删除客户方法的按钮; 首先我搜索实体,如果找到,然后我从数据库中的“客户”列表中删除该项目,如下所示:
private async Task DeleteCustomer(int CustomerId)
{
Customer? customer = clients.FirstOrDefault(f => f.Id == CustomerId);
if (customer is not null)
{
clients.Remove(customer);
await db.SaveChangesAsync();
}
}
问题是实体已从列表中删除但未从数据库中删除,因此当我刷新仍在那里的项目时,我必须在 if 中应用另一个命令以使其工作:
db.Remove(customer);
换句话说,我必须将它从客户列表和列表中删除,使工作加倍,在我看来它完全失去了来自数据库和数据库的列表之间的连接(或引用)。 这是我第一次看到这样的东西,我错过了什么吗? 我是否按照我应该做的方式使用 EF? 我可以添加该命令并使其工作,但我认为这不是一个好习惯,请帮助!
是的,那是因为这就是 EF 的工作方式。
客户端列表包含查询的元素。 即使删除后,它仍然是一个查询元素。 Ef 没有合乎逻辑的方法来更新客户端 - 特别是因为客户端是一个列表,它没有以合理的方式为此提供 API。
因此,您必须将其从两者中删除,这是合乎逻辑的。
其实你完全错了。 从客户端删除某些内容不会从 Ef 触发任何内容,因为开始没有任何意义。 我可以将它们删除然后在上面运行代码 - 并且会触发从数据库中自动删除只是为了在 UI 中过滤掉一些东西。 只有 db.Remove 实际上告诉 Ef 它是从数据库中删除它。 这不是双重的,是 Ef 没有神奇地读懂你的思想。
您必须从 dbcontext 中删除项目,而不是从列表中删除。 创建视图后,所有 dbcontext 都已处理,列表未连接。 当您尝试删除时,您已经拥有不同的数据库上下文。 所以你需要这个
public async Task DeleteCustomer(int CustomerId)
{
var customer = await db.Customers.FirstOrDefaultAsync(f => f.Id == CustomerId);
if (customer!=null)
{
db.Customers.Remove(customer);
var result= await db.SaveChangesAsync();
}
}
您需要使用dbcontext factory
,如下所示:
services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db")
.EnableSensitiveDataLogging());
/// <summary>
/// Context for the contacts database.
/// </summary>
public class ContactContext : DbContext
{
/// <summary>
/// Magic string.
/// </summary>
public static readonly string RowVersion = nameof(RowVersion);
/// <summary>
/// Magic strings.
/// </summary>
public static readonly string ContactsDb = nameof(ContactsDb).ToLower();
/// <summary>
/// Inject options.
/// </summary>
/// <param name="options">The <see cref="DbContextOptions{ContactContext}"/>
/// for the context
/// </param>
public ContactContext(DbContextOptions<ContactContext> options)
: base(options)
{
Debug.WriteLine($"{ContextId} context created.");
}
/// <summary>
/// List of <see cref="Contact"/>.
/// </summary>
public DbSet<Contact> Contacts { get; set; }
/// <summary>
/// Define the model.
/// </summary>
/// <param name="modelBuilder">The <see cref="ModelBuilder"/>.</param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// this property isn't on the C# class
// so we set it up as a "shadow" property and use it for concurrency
modelBuilder.Entity<Contact>()
.Property<byte[]>(RowVersion)
.IsRowVersion();
base.OnModelCreating(modelBuilder);
}
/// <summary>
/// Dispose pattern.
/// </summary>
public override void Dispose()
{
Debug.WriteLine($"{ContextId} context disposed.");
base.Dispose();
}
/// <summary>
/// Dispose pattern.
/// </summary>
/// <returns>A <see cref="ValueTask"/></returns>
public override ValueTask DisposeAsync()
{
Debug.WriteLine($"{ContextId} context disposed async.");
return base.DisposeAsync();
}
}
假设您有一个索引页面,您可以在其中显示联系人列表:
@inject IDbContextFactory<ContactContext> DbFactory
@code
{
protected async override Task OnInitializedAsync()
{
// When the Index page is created the ReloadAsync method
// is called to retrieve a list of contact objects
}
// When you delete a contact, it is removed both from the database
// and from the list that hold the contacts
private async Task DeleteContactAsync()
{
using var context = DbFactory.CreateDbContext();
Filters.Loading = true;
var contact = await context.Contacts.FirstAsync(
c => c.Id == Wrapper.DeleteRequestId);
if (contact != null)
{
context.Contacts.Remove(contact);
await context.SaveChangesAsync();
}
Filters.Loading = false;
await ReloadAsync();
}
private async Task ReloadAsync()
{
if (Filters.Loading || Page < 1)
{
return;
}
Filters.Loading = true;
if (Wrapper != null)
{
Wrapper.DeleteRequestId = 0;
}
Contacts = null;
using var context = DbFactory.CreateDbContext();
// run the query to load the current page
Contacts = await
QueryAdapter.FetchAsync(context.Contacts.AsQueryable());
// now we're done
Filters.Loading = false;
}
}
注意:这就是我们在 Blazor 中编码的方式。 最重要的特性是 Blazor 组件模型……重新渲染无处不在。 每次添加删除或更新联系人对象时,您都需要创建一个新的数据库上下文,执行操作,然后让它消失并更新您的联系人存储(在内存列表中)
请复制上面的内容,因为我很快就会删除它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.