问题:
我希望能够以一种方式扩展EF6,使我能够在EF edmx文件中的单个实体上定义缓存策略,事务策略,多租户等。我愿意和设计师一起做这件事。
我设法像http://www.databinding.net/blog/post/2010/12/02/entity-framework-4-benutzerdefinierte-eigenschaften-mit-dem-adonet-entity-data-model-designer-ext.html中建议的那样进行扩展 但在安装vsix后,属性不存在。重启VS等但没有工作。在VS 2013中我还需要做些什么吗?
有人做过类似的事吗?
答案 0 :(得分:2)
事实证明,EF6扩展很容易实现。首先,您必须遵循EF版本的MSDN文档。然后你必须为EF扩展制作2个项目,第二个是VS扩展项目(VSIX)。 在EF扩展项目中添加两个类:
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
}
}
}
请参阅MSDN为什么会这样。您可以通过为[EntityDesignerExtendedProperty(EntityDesignerSelection.ConceptualModelEntityType)]设置不同的值来定义挂钩的位置,再次参见MSDN。 我决定挂钩实体图选择。
然后在VSIX项目中添加Microsoft.VisualStudio.MefComponent类型的Asset,并选择EF扩展项目。构建解决方案。转到bin(调试或发布)并将所有文件复制到新文件夹。添加名为[Content_Types] .xml的新xml文件,其示例内容为:
<?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>
然后将所有压缩为zip并重命名为xxxx.vsix。将其安装到VS(在VSIX项目中定义为Install Target)。
重新启动VS并转到您选择的edmx。你会得到像这样的结果