对于我的数据库中的某些属性,我需要手动计算其ID#,因此对于这些属性,我在.Property(p => p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
内OnModelCreating
然后,在存储库中我有一个方法来计算给定类型的Id。我希望系统具有智能性,并检查DatabaseGeneratedOption.None
或DatabaseGeneratedOption.Identity
是否返回下一个Id或0。
如何检查(从存储库中)给定类型(T)的DatabaseGeneratedOption
是什么?
答案 0 :(得分:0)
感谢George的评论,我能够提出这个解决方案:
bool? _sqlGeneratesID;
bool IRepository<TEntity>.IsStoreGeneratedIdentity()
{
if (!_sqlGeneratesID.HasValue)
{
var items = (_context as IObjectContextAdapter)?.ObjectContext.MetadataWorkspace.GetItems(DataSpace.SSpace).OfType<EntityType>();
var entity = items.Single(x => x.Name == typeof(TEntity).Name);
_sqlGeneratesID = entity.KeyProperties.FirstOrDefault()?.IsStoreGeneratedIdentity ?? false;
}
return _sqlGeneratesID.Value;
}
答案 1 :(得分:0)
正如我在评论中所说,您的解决方案依赖于代码优先存储模型,从EntityType
返回CLR类型名称。但是,数据库优先存储模型返回商店名称。这些名称不一定与CLR类型名称匹配。
要使此方法独立于EF的商店模型,我们需要访问store-CLR映射空间(CSSpace
)并找到EntitySet
(按CLR名称)并匹配其KeyMembers
包含商店模型中的列(Property.Column
),因为这些列包含正确的IsStoreGeneratedIdentity
值。 (CLR属性也有此属性,但它总是错误的。)
所以这就是我们得到的(作为封装在DbContext
子类型中的方法):
public bool IsStoreGeneratedIdentity<TEntity>()
{
var entityContainerMappings = (this as IObjectContextAdapter).ObjectContext
.MetadataWorkspace.GetItems(DataSpace.CSSpace)
.OfType<EntityContainerMapping>();
var entityTypeMappings = entityContainerMappings
.SelectMany(m => m.EntitySetMappings
.Where(esm => esm.EntitySet.ElementType.Name == typeof(TEntity).Name))
.SelectMany(esm => esm.EntityTypeMappings).ToArray();
var keyMappings = (from km in entityTypeMappings.SelectMany(etm => etm.EntityType.KeyMembers)
join pm in entityTypeMappings.SelectMany(etm => etm.Fragments)
.SelectMany(mf => mf.PropertyMappings)
.OfType<ScalarPropertyMapping>()
on km.Name equals pm.Property.Name
select pm
);
return keyMappings.Any(pm => pm.Column.IsStoreGeneratedIdentity);
}