问题
The problem:
I want to be able to extend EF6 in a way that enables me to define Caching policy, Transactional policy, Multi-tenancy , etc on a single entity in an EF edmx file. I am willing doing this with designer.
I've managed to make an extension like suggested in http://www.databinding.net/blog/post/2010/12/02/entity-framework-4-benutzerdefinierte-eigenschaften-mit-dem-adonet-entity-data-model-designer-ext.html but after installing the vsix the properties are not there. Restarted VS etc but not working. Is something I have to do more in VS 2013?
Has somebody done something similar?
回答1:
It turns out that EF6 extensions are quiet simple to implement. First you have to follow the MSDN docs for your EF version. Then you have to Make 2 project one for the EF extension and the second is the VS extension project (VSIX). In the EF extension project add two classes:
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Data.Entity.Design.Extensibility;
namespace SaopEdmxExtenstions
{
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IEntityDesignerExtendedProperty))]
[EntityDesignerExtendedProperty(EntityDesignerSelection.ConceptualModelEntityType)]
public class EfDesignerCustomPropertiesFactory : IEntityDesignerExtendedProperty
{
public object CreateProperty(XElement element, PropertyExtensionContext context)
{
return new EfDesignerCustomProperties(element, context);
}
}
public class EfDesignerCustomProperties
{
internal static readonly string Namespace = "http://saop.si";
internal static XName NsBaseDiagram = XName.Get("CachingType", Namespace);
internal const string Category = "Saop Edmx Extensions";
private readonly XElement _parent;
private readonly PropertyExtensionContext _context;
public EfDesignerCustomProperties(XElement parent, PropertyExtensionContext context)
{
_context = context;
_parent = parent;
}
[DisplayName("Caching Type")]
[Description("Specifies how to handle entity Caching")]
[Category(EfDesignerCustomProperties.Category)]
[DefaultValue(CachingType.None)]
public CachingType CustomCachingType
{
get
{
var propertyValue = CachingType.None;
if (!_parent.HasElements) return propertyValue;
foreach (XElement element in _parent.Elements())
{
if (element.Name != EfDesignerCustomProperties.NsBaseDiagram) continue;
var bv = element.Value.Trim();
switch (bv)
{
case "None": propertyValue = CachingType.None; break;
case "Application": propertyValue = CachingType.Application; break;
case "Request": propertyValue = CachingType.Request; break;
case "Session": propertyValue = CachingType.Session; break;
}
}
return propertyValue;
}
set
{
CachingType propertyValue = value;
using (EntityDesignerChangeScope scope = _context.CreateChangeScope("Set Entity Caching"))
{
if (_parent.HasElements)
{
var updated = false;
foreach (XElement element in _parent.Elements())
{
if (element.Name != EfDesignerCustomProperties.NsBaseDiagram) continue;
element.SetValue(propertyValue.ToString().Trim());
updated = true;
break;
}
if (!updated)
{
var lastChild = _parent.Elements().Last();
lastChild.AddAfterSelf(new XElement(NsBaseDiagram, propertyValue));
}
}
else
{
_parent.Add(new XElement(NsBaseDiagram, propertyValue.ToString().Trim()));
}
scope.Complete();
}
}
}
[DisplayName("Is Multi-Tenant")]
[Description("Specifies if the entity is multi-tenant")]
[Category(EfDesignerCustomProperties.Category)]
[DefaultValue(false)]
public bool IsMultitTenant
{
get
{
var propertyValue = false;
if (!_parent.HasElements) return propertyValue;
foreach (XElement element in _parent.Elements())
{
if (element.Name != EfDesignerCustomProperties.NsBaseDiagram) continue;
var bv = element.Value.Trim();
switch (bv.ToLower())
{
case "false": propertyValue = false; break;
case "true": propertyValue = true; break;
}
}
return propertyValue;
}
set
{
var propertyValue = value;
using (EntityDesignerChangeScope scope = _context.CreateChangeScope("Set MultiTenancy"))
{
if (_parent.HasElements)
{
var updated = false;
foreach (XElement element in _parent.Elements())
{
if (element.Name != EfDesignerCustomProperties.NsBaseDiagram) continue;
element.SetValue(propertyValue.ToString().Trim());
updated = true;
break;
}
if (!updated)
{
var lastChild = _parent.Elements().Last();
lastChild.AddAfterSelf(new XElement(NsBaseDiagram, propertyValue));
}
}
else
{
_parent.Add(new XElement(NsBaseDiagram, propertyValue.ToString().Trim()));
}
scope.Complete();
}
}
}
public enum CachingType
{
None,
Request,
Session,
Application
}
}
}
see MSDN why is that way. You can define where to hook by setting different value for [EntityDesignerExtendedProperty(EntityDesignerSelection.ConceptualModelEntityType)] , again see MSDN. I've decided to hook on Entity diagram select.
Then In the VSIX project add an Asset of type Microsoft.VisualStudio.MefComponent and select the EF extension project. Build the solution. Go to bin's (debug or release) and copy all files to a new folder. Add a new xml file named [Content_Types].xml with the sample content of:
<?xml version="1.0" encoding="utf-8" ?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="vsixmanifest" ContentType="text/xml" />
<Default Extension="dll" ContentType="application/octet-stream" />
<Default Extension="png" ContentType="application/octet-stream" />
<Default Extension="txt" ContentType="text/plain" />
<Default Extension="pkgdef" ContentType="text/plain" />
</Types>
Then compress all as a zip and rename it so xxxx.vsix. Install it to VS (defined as Install Target in the VSIX project).
Restart VS and go to an edmx of your choice. You will se the results like this

来源:https://stackoverflow.com/questions/25446746/extending-entity-framework-6-adding-custom-properties-to-entities-in-designer