扩展实体框架6 - 向设计器中的实体添加自定义属性

时间:2014-08-22 12:11:04

标签: edmx

问题:

我希望能够以一种方式扩展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中我还需要做些什么吗?

有人做过类似的事吗?

1 个答案:

答案 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。你会得到像这样的结果

enter image description here