我正在使用 xUnit 和 FluentAssertions 撰寫集成測驗來驗證我們的模型是否正確映射。我們有幾十個 EF 背景關系,對于每個背景關系,都有一個或多個DbSet<>類似這樣的屬性:
public class SomeContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder builder) { // ... }
public virtual DbSet<User> Users { get; set; }
}
它們都以相同的方式布局,因此這將是用于[MemberData]動態獲取每個背景關系作為測驗和DbSet<>屬性的輸入、呼叫它并確保它不會在執行簡單查詢時失敗的理想選擇。該Container.GetInstance()呼叫是對我的 DI 容器的呼叫以獲取實際DbContext物件:
public class ContextTests
{
public static IEnumerable<object[]> EntitiesMappedInCode =>
typeof(DbContextInitializer).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(DbContext)) && !t.IsAbstract)
.SelectMany(dbContextType =>
{
var context = (DbContext) Container.GetInstance(dbContextType);
var entities = context.Model.GetEntityTypes();
var dbSetProperties = context.GetType().GetProperties().Where(p =>
typeof(DbSet<>).IsAssignableFrom(p.PropertyType.GetGenericTypeDefinition()));
return dbSetProperties.Select(dbSet => new [] {context, dbSet.GetValue(context)});
});
[Theory]
[MemberData(nameof(EntitiesMappedInCode))]
public void EntitiesDefinedInCode_ExistsInDatabase(DbContext context, object dbSetObject)
{
var dbSet = dbSetObject as DbSet<dynamic>;
dbSet.Invoking(dbSet => Queryable.FirstOrDefault<dynamic>(dbSet))
.Should().NotThrow<SqlException>("the entity framework model should match the database");
}
}
問題是反射無法正常作業以回傳運行時實體并且失敗p.PropertyType.GetGenericTypeDefinition()并出現錯誤。
有沒有人動態檢索DbSet<>背景關系的屬性并成功呼叫它們的查詢?
uj5u.com熱心網友回復:
拋出例外是因為GetGenericTypeDefinition()它不適用于非泛型型別,所以在呼叫它之前你應該首先檢查型別是否真的是泛型的:
var dbSetProps = typeof(HwContext).GetProperties().Where(c =>
c.PropertyType.IsGenericType &&
typeof(DbSet<>).IsAssignableFrom(c.PropertyType.GetGenericTypeDefinition()));
也不要強制轉換為DbSet<dynamic>,只需使用dynamic:
foreach (var prop in dbSetProps)
{
dynamic dbSet = prop.GetValue(context);
// this should not throw
Queryable.FirstOrDefault(dbSet);
}
uj5u.com熱心網友回復:
感謝 Evk,我能夠讓它像這樣作業:
public class ContextTests
{
public static IEnumerable<object[]> EntitiesMappedInCode =>
typeof(DbContextInitializer).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(DbContext)) && !t.IsAbstract)
.SelectMany(dbContextType =>
{
var dbSetProps = dbContextType.GetProperties()
.Where(c => c.PropertyType.IsGenericType
&& typeof(DbSet<>).IsAssignableFrom(c.PropertyType.GetGenericTypeDefinition()));
var context = Container.GetInstance(dbContextType);
return dbSetProps.Select(dbSetProp => new [] {context, dbSetProp.GetValue(context)});
});
[Theory]
[MemberData(nameof(EntitiesMappedInCode))]
public void EntitiesDefinedInCode_ExistsInDatabase(DbContext context, dynamic dbSet)
{
context.Invoking(dbContext => Queryable.FirstOrDefault(dbSet))
.Should().NotThrow<SqlException>("the entity framework model should match the database");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/356458.html
