我使用了Entity Framework Core
并更新了一些与另一个对象有关的对象。
我有以下实体:
客户端:
public class Client
{
public int Id { get; set; }
public string ClientId { get; set; }
public string ClientName { get; set; }
public List<ClientScope> Scopes { get; set; }
}
ClientScope:
public class ClientScope
{
public int Id { get; set; }
public string Scope { get; set; }
public Client Client { get; set; }
}
OnModelCreating:
modelBuilder.Entity<Client>((Action<EntityTypeBuilder<Client>>) (client =>
{
client.ToTable<Client>(storeOptions.Client);
client.HasKey((Expression<Func<Client, object>>) (x => (object) x.Id));
client.Property<string>((Expression<Func<Client, string>>) (x => x.ClientId)).HasMaxLength(200).IsRequired(true);
client.HasIndex((Expression<Func<Client, object>>) (x => x.ClientId)).IsUnique(true);
client.HasMany<ClientScope>((Expression<Func<Client, IEnumerable<ClientScope>>>) (x => x.AllowedScopes)).WithOne((Expression<Func<ClientScope, Client>>) (x => x.Client)).IsRequired(true).OnDelete(DeleteBehavior.Cascade);
}));
modelBuilder.Entity<ClientScope>((Action<EntityTypeBuilder<ClientScope>>) (scope =>
{
scope.ToTable<ClientScope>(storeOptions.ClientScopes);
scope.Property<string>((Expression<Func<ClientScope, string>>) (x => x.Scope)).HasMaxLength(200).IsRequired(true);
}));
我想更新特定ClientScope
的{{1}},例如Id = 1。
我尝试过这种方式:
Client.Id
但这种方式也尝试更新public void UpdateClientScope(ClientScope scope){
_dbContext.ClientScope.Update(scope);
_dbContext.SaveChanges();
}
var scope = new ClientScope() { Client = new Client{Id = 1}, Id = 1, Scope = "Test Scope" }
UpdateClientScope(scope);
。我想只更新ClientScope并指定存储在表单上的ClientId。
上面更新Client
的最佳方式是什么?
我试图实现我想为每个实体实现的ClientScope
:
BaseRepository
但我不知道 - 如何为这样的实体正确指定public class BaseRepository<TDbContext, TEntity, TPrimaryKey> : IBaseRepository<TDbContext, TEntity, TPrimaryKey>
where TEntity : class
where TDbContext : DbContext
{
public virtual DbSet<TEntity> Table => _dbContext.Set<TEntity>();
private readonly TDbContext _dbContext;
public BaseRepository(TDbContext dbContext)
{
_dbContext = dbContext;
}
public virtual async Task<TEntity> UpdateAsync(TEntity entity)
{
Table.Update(entity);
await _dbContext.SaveChangesAsync();
return entity;
}
}
方法?
感谢您的任何建议。
答案 0 :(得分:3)
如果您从未计划通过存储库方法添加或修改相关实体,则只需设置所有其他实体即可。状态为EntityState.Unchanged
,例如:
public virtual async Task<TEntity> UpdateAsync(TEntity entity)
{
Table.Update(entity);
foreach( var entry in _dbContext.ChangeTracker.Entries() )
{
if( entry.Entity != entity )
{
entry.State = EntityState.Unchanged;
}
}
await _dbContext.SaveChangesAsync();
return entity;
}
或者,在调用repo方法之前,将相关实体附加为未更改。也许创建一个repo方法来返回这样一个实体:
public TEntity GetEntityPlaceholder( int id )
{
var entity = new TEntity() { Id = id };
_dbContext.Attach( entity );
return entity;
}
我更喜欢FK属性,我自己:
public class ClientScope
{
public int Id { get; set; }
public string Scope { get; set; }
public Client Client { get; set; }
// FK, use [ForeignKey( "Client" )] if you wish
public int ClientId { get; set; }
}
// or use FluentAPI
modelBuilder.Entity<ClientScope>()
.HasRequired( cs => cs.Client )
.WithMany( c => c.Scopes )
// specify foreign key
.HasForeignKey( cs => cs.ClientId );
// now can specify a client by setting the ClientId property
var scope = new ClientScope()
{
ClientId = 1,
Id = 1,
Scope = "Test Scope",
}
UpdateClientScope(scope);
答案 1 :(得分:2)
正如评论中所提到的(感谢Ivan),EF需要“了解”您要更新的对象。
很抱歉,我没有任何东西可以用来测试,但你的UpdateClientScope方法应该是这样的:
public void UpdateClientScope(ClientScope scope){
// Get the existing object from the DB
ClientScope dbScope = _dbContext.ClientScope.FirstOrDefault(x => x.Id == scope.Id);
// Test it was in DB
if (dbScope != null)
{
// Update the database object
dbScope.Scope = scope.Scope;
dbScope.Client = scope.Client;
// SaveChanges works on dbScope
_dbContext.SaveChanges();
}
else
{
// Object not found, some error processing
}
}
答案 2 :(得分:1)
我不明白哪里有问题?通过DBContext对象,您可以访问除对象属性之外的任何类对象,而不仅仅使用简单的赋值运算符更改属性值,只需更改DbContext.SaveChanges(),您的更改将在数据库列中更新,完全没有问题。如果你想要单独的Update()方法进行更改,你可以使用几个代码行或更复杂的方式使用C#Reflection可能性,但我无法想象为什么你需要它?如果我错过了什么告诉我更多。祝好运 !!!!
答案 3 :(得分:0)
我认为您的实体为false,因为您的ClientScope没有clientId(外键)。
public string ClientId {get;组;这条线做什么?