Entity framework 4 自动在EDMX中设置要修复的并发模式

Entity framework 4 自动在EDMX中设置要修复的并发模式,entity-framework-4,concurrency,edmx,Entity Framework 4,Concurrency,Edmx,我们模型中的大多数表都有一个名为“intConcurrencyID”的字段,我们打算将其用于并发检查。我认为在Database First环境中启用此字段进行并发检查的唯一方法是将并发模式设置为Fixed 但是,如果每个EDMX有大量的表,我们将很难手动配置每个实体的每种类型,更不用说可能会忽略某些实体 你对我如何使这个过程自动化有什么想法吗?T4模板似乎不是一个好办法,因为并发模式在CSDL中,而不是在代码隐藏中。我在更改属性的并发模式之前和之后查看了edmx文件,并提出了一个解决方案,作为控

我们模型中的大多数表都有一个名为“intConcurrencyID”的字段,我们打算将其用于并发检查。我认为在Database First环境中启用此字段进行并发检查的唯一方法是将并发模式设置为Fixed

但是,如果每个EDMX有大量的表,我们将很难手动配置每个实体的每种类型,更不用说可能会忽略某些实体


你对我如何使这个过程自动化有什么想法吗?T4模板似乎不是一个好办法,因为并发模式在CSDL中,而不是在代码隐藏中。

我在更改属性的并发模式之前和之后查看了edmx文件,并提出了一个解决方案,作为控制台应用程序,它从存储模型开始解析edmx文件的“timestamp”列,并修改按照映射建立概念模型。这是一个相当健壮的解决方案,但有一些警告

我使用的是MSSQL 2008,它的timestamp/rowversion实际上是并发类型。在我的模型中,我只将此类型用作并发令牌。如果您在其他地方使用它,但是所有并发令牌都使用了一致的名称,那么我已经为这个场景提供了可以取消注释的代码。如果您只是使用不同的并发类型,并且该类型对于并发列是唯一的,那么您可以在这行代码中将该类型从“timestamp”更改为:

           IEnumerable<XElement> storageEntities =
            from el in ssdl.Descendants(XName.Get("EntityType",ssdlNS))
            where (from prop in el.Elements(XName.Get("Property",ssdlNS)) where prop.Attribute("Type").Value == "timestamp" select prop).Count()>0
            select el;
IEnumerable存储实体=
来自ssdl.substands(XName.Get(“EntityType”,ssdlNS))中的el
其中(从el.Elements(XName.Get(“Property”,ssdlNS))中的prop.Attribute(“Type”).Value==“timestamp”选择prop.Count()>0
选择el;
如果并发模式更复杂,那么这段代码就不够了

话虽如此,我在大约一个小时内完成了这项工作,并运行了它,它在一个拥有近200个实体的模型上对我非常有效,为我省去了很多通过迟缓的edmx设计器的麻烦,因此我相信其他人会受益。这是一个控制台应用程序,因此您可以将其放在模型项目的预构建步骤中,以将其集成到构建过程中

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

namespace ConfigureConcurrency
{
    class Program
    {
        static void Main(string[] args)
        {
            string edmxPath = args[0]; //or replace with a fixed path

            if (edmxPath == null || edmxPath.Length == 0)
                return;

            string edmxNS = @"http://schemas.microsoft.com/ado/2008/10/edmx";
            string ssdlNS = @"http://schemas.microsoft.com/ado/2009/02/edm/ssdl";
            string csdlNS = @"http://schemas.microsoft.com/ado/2008/09/edm";
            string mapNS = @"http://schemas.microsoft.com/ado/2008/09/mapping/cs";

            XElement root = XElement.Load(edmxPath);
            //Storage Model
            XElement ssdl = root.Descendants(XName.Get("StorageModels", edmxNS)).FirstOrDefault();
            //Conceptual
            XElement csdl = root.Descendants(XName.Get("ConceptualModels", edmxNS)).FirstOrDefault();
            //Mapping
            XElement map = root.Descendants(XName.Get("Mappings", edmxNS)).FirstOrDefault();

            /*
             Use this code instead of the line below it, if the type of your concurrency columns is used on other non-concurrency columns
             and you use the same name for every concurrency column             

            string ConcurrencyColumnName = "RowVersion";
            IEnumerable<XElement> storageEntities =
                from el in ssdl.Descendants(XName.Get("EntityType", ssdlNS))
                where (from prop in el.Elements(XName.Get("Property", ssdlNS)) where prop.Attribute("Name").Value == ConcurrencyColumnName select prop).Count() > 0
                select el;
            */

            IEnumerable<XElement> storageEntities =
                from el in ssdl.Descendants(XName.Get("EntityType",ssdlNS))
                where (from prop in el.Elements(XName.Get("Property",ssdlNS)) where prop.Attribute("Type").Value == "timestamp" select prop).Count()>0
                select el;

            //for each timestamp column, find the mapping then find the conceptual model property and establish the concurrency mode
            foreach(XElement storageEntity in storageEntities) 
            {
                //Get the mapping
                XElement mapping = (from el in map.Descendants(XName.Get("EntityTypeMapping",mapNS)) where el.Element(XName.Get("MappingFragment",mapNS)).Attribute("StoreEntitySet").Value == storageEntity.Attribute("Name").Value select el).FirstOrDefault();

                if (mapping != null)
                {
                    //Get the column mapping
                    XElement column = (from el in storageEntity.Descendants(XName.Get("Property",ssdlNS)) where el.Attribute("Type").Value == "timestamp" select el).FirstOrDefault();
                    string columnName = column.Attribute("Name").Value;
                    XElement columnMapping = (from el in mapping.Descendants(XName.Get("ScalarProperty",mapNS)) where el.Attribute("ColumnName").Value == columnName select el).FirstOrDefault();
                    string propertyName = columnMapping.Attribute("Name").Value;

                    //Get the conceptual schema namespace and type name
                    string[] split = mapping.Attribute("TypeName").Value.Split('.');

                    string ns="", typeName =split[split.Length-1];

                    for (int i = 0; i < split.Length-1; i++)
                    {
                        if (i>0)
                            ns+=".";

                        ns += split[i];
                    }

                    //Find the entry in the conceptual model
                    XElement schema = (from el in csdl.Elements(XName.Get("Schema",csdlNS)) where el.Attribute("Namespace").Value == ns select el).FirstOrDefault();

                    if (schema != null)
                    {
                        //Find the entity type
                        XElement entity = (from el in schema.Descendants(XName.Get("EntityType",csdlNS)) where el.Attribute("Name").Value == typeName select el).FirstOrDefault();

                        //Find the property
                        XElement concurrencyProperty = (from el in entity.Elements(XName.Get("Property",csdlNS)) where el.Attribute("Name").Value == propertyName select el).FirstOrDefault();

                        //Set concurrency mode to fixed
                        concurrencyProperty.SetAttributeValue("ConcurrencyMode", "Fixed");
                    }
                }
            }

            //Save the modifications
            root.Save(edmxPath);


        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Xml;
使用System.Xml.Linq;
命名空间配置并发性
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串edmxPath=args[0];//或替换为固定路径
if(edmxPath==null | | edmxPath.Length==0)
回来
字符串edmxNS=@”http://schemas.microsoft.com/ado/2008/10/edmx";
字符串ssdlNS=@”http://schemas.microsoft.com/ado/2009/02/edm/ssdl";
字符串csdlNS=@”http://schemas.microsoft.com/ado/2008/09/edm";
字符串mapNS=@”http://schemas.microsoft.com/ado/2008/09/mapping/cs";
XElement root=XElement.Load(edmxPath);
//存储模型
XElement ssdl=root.substands(XName.Get(“StorageModels”,edmxNS)).FirstOrDefault();
//概念的
XElement csdl=root.substands(XName.Get(“ConceptualModels”,edmxNS)).FirstOrDefault();
//映射
XElement map=root.substands(XName.Get(“Mappings”,edmxNS)).FirstOrDefault();
/*
如果并发列的类型用于其他非并发列,请使用此代码,而不是它下面的行
每个并发列都使用相同的名称
字符串ConcurrencyColumnName=“RowVersion”;
IEnumerable存储实体=
来自ssdl.substands(XName.Get(“EntityType”,ssdlNS))中的el
其中(从el.Elements(XName.Get(“Property”,ssdlNS))中的prop.Attribute(“Name”).Value==ConcurrencyColumnName选择prop.Count()>0
选择el;
*/
IEnumerable存储实体=
来自ssdl.substands(XName.Get(“EntityType”,ssdlNS))中的el
其中(从el.Elements(XName.Get(“Property”,ssdlNS))中的prop.Attribute(“Type”).Value==“timestamp”选择prop.Count()>0
选择el;
//对于每个时间戳列,找到映射,然后找到概念模型属性并建立并发模式
foreach(storageEntities中的XElement storageEntity)
{
//获取映射
XElement mapping=(来自map.Substands(XName.Get(“EntityTypeMapping”,mapNS))中的el,其中el.Element(XName.Get(“MappingFragment”,mapNS)).Attribute(“StoreEntitySet”).Value==storageEntity.Attribute(“Name”).Value选择el.FirstOrDefault();
if(映射!=null)
{
//获取列映射
XElement列=(来自storageEntity.subjects(XName.Get(“Property”,ssdlNS))中的el,其中el.Attribute(“Type”).Value==“timestamp”选择el.FirstOrDefault();
字符串columnName=column.Attribute(“Name”).Value;
XElement columnMapping=(来自mapping.substands(XName.Get(“ScalarProperty”,mapNS))中的el,其中el.Attribute(“ColumnName”).Value==ColumnName选择el.FirstOrDefault();
string propertyName=columnMapping.Attribute(“Name”).Value;
//获取概念架构名称空间和类型名称
string[]split=mapping.Attribute(“TypeName”).Value.split('.');
字符串ns=”“,typeName=split[split.Length-1];
对于(int i=0;i0)
ns+=“;
ns+=split[i];
}
//在概念模型中查找条目
XElement schema=(来自csdl.Elements(XName.Get(“schema”)中的el)
string edmxNS = @"http://schemas.microsoft.com/ado/2009/11/edmx";
string ssdlNS = @"http://schemas.microsoft.com/ado/2009/11/edm/ssdl";
string csdlNS = @"http://schemas.microsoft.com/ado/2009/11/edm";
string mapNS = @"http://schemas.microsoft.com/ado/2009/11/mapping/cs";