ConcurrencyMode automation installed on fix in EDMX

Most of our tables in our models have a field called "intConcurrencyID", which we intended to use to check concurrency. I believe that the only way to enable this field for checking concurrency in the Database First environment is to set the concurrency mode to fix.

However, if we have a huge number of tables on EDMX, it will be difficult for us to manually configure each type for each object, not to mention the possibility of excluding some objects.

Do you have any ideas on how I can automate this process? It seems that the T4 Template is not the way to go, as the concurrency mode is in the CSDL and not in the code below.

+2
source share
2 answers

I looked at the edmx file before and after changing the mode of concurrency properties and came up with a solution as a console application that parses the edmx file, starting with the storage model for timestamp columns, and changing the conceptual model to after mappings. This is a fairly reliable solution, but it has some reservations.

I am using MSSQL 2008 for which timestamp / rowversion is a type of defacto concurrency. In my models, I use this type only as a concurrency token. If you use it elsewhere but use a consistent name for all concurrency tokens instead, I have included code for this script that can be uncommented. If you just use a different type of concurrency, and this type is unique to concurrency columns, you can change the type from "timestamp" in this line of code:

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; 

If your concurrency template is more complex, this code will not be enough.

Having said that, I freaked out about an hour later and started it, and he did a great job on my model with almost 200 objects, saving me a lot of annoyance going through the languid edmx designer, so I'm sure others will benefit. This is a console application, so you can put it in the pre-build phase of your model project to integrate it into your build process.

 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); } } } 
+3
source

Solved my similar problem with the above console application. But if you are using a later version of the Entity Framework, be sure to update the links to the schemas. I am using EF 5 and for me I used the following lines:

 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"; 
+1
source

Source: https://habr.com/ru/post/1498416/


All Articles