Reputation: 41
I develop method, which resets cache, when Entity Framework is saving changes. I handle this event in objectContext_SavingChanges
private void objectContext_SavingChanges(object sender, EventArgs e)
{
if (_cacheProvider != null)
{
var objectContext = (this as IObjectContextAdapter).ObjectContext;
var entries =
objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added);
var result = new List<string>();
if (entries != null && entries.Any())
{
foreach (var entry in entries.Where(entry => !entry.IsRelationship))
{
var entity = entries.Select(r => r.Entity).FirstOrDefault();
if (entity != null)
{
var genericTypeName =
typeof(List<>).MakeGenericType(ObjectContext.GetObjectType(entity.GetType()))?.ToString();
_cacheProvider.ResetCache(genericTypeName);
}
}
foreach (var entry in entries.Where(entry => entry.IsRelationship))
{
var set = entry.EntitySet as AssociationSet;
if(set !=null)
{
var firstEntitySet = set.AssociationSetEnds[0].EntitySet;
var secondEntitySet = set.AssociationSetEnds[1].EntitySet;
var firstEntitySetName = firstEntitySet.ElementType.FullName + "," + Assembly.GetExecutingAssembly().FullName;
var secondEntitySetName = secondEntitySet.ElementType.FullName + "," + Assembly.GetExecutingAssembly().FullName;
var firstGenericTypeName =
typeof(List<>).MakeGenericType((Type.GetType(firstEntitySetName)))?.ToString();
var secondGenericTypeName =
typeof(List<>).MakeGenericType((Type.GetType(secondEntitySetName)))?.ToString();
_cacheProvider.ResetCache(firstGenericTypeName);
_cacheProvider.ResetCache(secondGenericTypeName);
}
}
}
}
}
It works great for entity's entries of object state entries, but does not work for association sets. I need to reset cache for both entities on other sides of relation. AssociationSet has "FullName" property but this property does not contain real name of type. It contains short name of type and assembly name, but not contains full namespace in solution.
For example, type has real full name in solution DataAccess.Entities.CachedEntity
, namespace: DataAccess.Entities
, short name: CachedEntity
. But full name in association set will be DataAccess.CachedEntity
.
Can I get full name of type for each end of relation?
Upvotes: 1
Views: 383
Reputation: 41
I decided this task so:
var clrTypeNamespace = @"http://schemas.microsoft.com/ado/2013/11/edm/customannotation:ClrType";
var firstEdmType = set.AssociationSetEnds[0]?.EntitySet?.ElementType;
var secondEdmType = set.AssociationSetEnds[1]?.EntitySet?.ElementType;
var firstType = firstEdmType?.MetadataProperties.SingleOrDefault(p => p.Name == clrTypeNamespace)?.Value as Type;
var secondType = secondEdmType?.MetadataProperties.SingleOrDefault(p => p.Name == clrTypeNamespace)?.Value as Type;
We can use namespace clrTypeNamespace
of CLR type in EDM and find real type of entity in MetadataProperties
Also, we can use navigation properies for each relationship's set. But this solution is sutable for situations, when navigation properties exist on both sides of relationship.
var asem = set.AssociationSetEnds[0].CorrespondingAssociationEndMember;
var propInfo = asem.MetadataProperties.SingleOrDefault(p => p.Name == "ClrPropertyInfo")?.Value as PropertyInfo;
Upvotes: 1