如何使用EntityFramework Core

时间:2017-09-21 07:21:30

标签: c# entity-framework entity-framework-core

我使用了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; } } 方法?

感谢您的任何建议。

4 个答案:

答案 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;组;这条线做什么?