C# 实体框架-确定给定类型的HasDatabaseGenerateOption设置
对于数据库中的某些属性,我需要手动计算它们的Id#,因此对于那些属性,我需要C# 实体框架-确定给定类型的HasDatabaseGenerateOption设置,c#,entity-framework,reflection,C#,Entity Framework,Reflection,对于数据库中的某些属性,我需要手动计算它们的Id#,因此对于那些属性,我需要.Property(p=>p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)内部OnModelCreating 然后,在存储库中,我有一个方法来计算给定类型的Id。我希望系统是智能的,并检查DatabaseGeneratedOption.None或Databa
.Property(p=>p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)代码>内部OnModelCreating
然后,在存储库中,我有一个方法来计算给定类型的Id。我希望系统是智能的,并检查DatabaseGeneratedOption.None
或DatabaseGeneratedOption.Identity
是否返回下一个Id或0
如何(从存储库中)检查给定类型(T)的数据库生成选项是什么?多亏了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;
}
bool_sqlGeneratesID;
bool IRepository.IsStoreGeneratedIdentity()
{
if(!\u sqlGeneratesID.HasValue)
{
var items=(_context作为IObjectContextAdapter)?.ObjectContext.MetadataWorkspace.GetItems(DataSpace.SSpace.OfType();
var实体=items.Single(x=>x.Name==typeof(tenty.Name);
_sqlGeneratesID=entity.KeyProperties.FirstOrDefault()?.IsStoreGenerateDidentiality??false;
}
返回_sqlGeneratesID.Value;
}
正如我在一篇评论中所说,您的解决方案是通过一个代码优先存储模型工作的,该模型从EntityType
返回CLR类型名称。但是,数据库第一存储模型返回存储名称。这些名称不一定与CLR类型名称匹配
为了使此方法独立于EF的存储模型,我们需要访问存储CLR映射空间(CSSpace
),找到EntitySet
(按CLR名称),并将其KeyMembers
与存储模型中的列(属性.Column
)匹配,因为这些列包含正确的值IsStoreGeneratedIdentity
。(CLR属性也有此属性,但它始终为false)
这就是我们得到的(作为封装在DbContext
子类型中的方法):
public bool isstoregeneratedintity()
{
var entityContainerMappings=(此为IObjectContextAdapter)。ObjectContext
.MetadataWorkspace.GetItems(DataSpace.CSSpace)
.of type();
var entityTypeMappings=entityContainerMappings
.SelectMany(m=>m.EntitySetMappings)
.Where(esm=>esm.EntitySet.ElementType.Name==typeof(tenty.Name))
.SelectMany(esm=>esm.EntityTypeMappings).ToArray();
var keyMappings=(从entityTypeMappings.SelectMany中的km开始)(etm=>etm.EntityType.KeyMembers)
在entityTypeMappings中加入pm.SelectMany(etm=>etm.Fragments)
.SelectMany(mf=>mf.PropertyMappings)
第()类
在km.Name上等于pm.Property.Name
选择pm
);
返回keyMappings.Any(pm=>pm.Column.IsStoreGeneratedIdentity);
}
看看这个,如果表名和类名不匹配,可能会帮助您停止工作。不是所有的表名都匹配。我将返回具有全名的项目,如“CodeFirstDatabaseSchema.Trait”
,并且在所有情况下,名称都等于类/类型名称。我看到的唯一例外是系统自动生成的表,用于将列表链接到实体。。。也许我只是走运了。但这对我有用DOK,你先写代码。使用数据库优先,如果查询存储模型,您将获得表名。是,代码优先。很高兴知道我是否需要先与DB合作(有时也需要)。谢谢
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);
}