プロパティの同時実行モードを変更する前後の edmx ファイルを見て、「タイムスタンプ」列のストレージ モデルから始まる edmx ファイルを解析し、マッピングに従って概念モデルを変更するコンソール アプリとしてのソリューションを考え出しました。これはかなり堅牢なソリューションですが、いくつかの注意点があります。
タイムスタンプ/行バージョンが事実上の同時実行型である MSSQL 2008 を使用しています。私のモデルでは、この型を同時実行トークンとしてのみ使用します。他の場所で使用しているが、代わりにすべての同時実行トークンに一貫した名前を使用している場合は、コメントを外すことができるこのシナリオのコードを含めました。別の同時実行タイプを使用するだけで、そのタイプが同時実行列に固有のものである場合は、次のコード行でタイプを「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;
同時実行パターンがより複雑な場合、このコードでは不十分です。
そうは言っても、これを約1時間で作成して実行したところ、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);
}
}
}