SQL2008
データベースに次のテーブルがあります。
宿泊施設
code varchar(18)
name varchar(80)
このテーブルにはさらに列がありますが、簡単にするためにここではそれらを削除しました。
属性
code int
name varchar(50)
宿泊施設の属性
AccommodationCode varchar(18)
AttributeCode int
お分かりかもしれませんが、宿泊施設属性は、宿泊施設と属性の間の多対多の関係を表しています。
最初にデータベースを使用してモデル (EF5) を作成し、ナビゲーション プロパティにリンクされた 2 つのクラスを作成しました。
これはすべて正しいようです。
私がやろうとしているのは、データベースに値を追加することですが、宿泊施設と属性を追加することはできますが、宿泊施設属性テーブルに対応する値を追加することはできないようです。
XMLファイルから読んでいます。
編集
以下は、私がそのまま使用しているコードです。
public static void UpdateAccommodation(string file)
{
InterHomeEntities ih = new InterHomeEntities();
Stopwatch sw = new Stopwatch();
ih.Configuration.AutoDetectChangesEnabled = false;
ih.Configuration.ValidateOnSaveEnabled = false;
ih.Configuration.LazyLoadingEnabled = false;
XElement xe = XElement.Load(file);
DateTime DayToProcess = DateTime.Now.AddDays(Properties.Settings.Default.InterHome_DaysToProcess);
var Attributes = xe.XPathSelectElements("//attribute").Select(x => x.Value).Distinct();
foreach (var attribute in Attributes)
{
Attribute at = ih.Attributes.Where(x => x.name == attribute).SingleOrDefault();
bool newEntry = at == null ? true : false;
at = newEntry ? new Attribute { name = attribute } : at;
ih.Attributes.Attach(at);
ih.Entry(at).State = newEntry ? System.Data.EntityState.Added : System.Data.EntityState.Modified;
ih.SaveChanges();
}
var Accommodations = from c in xe.Elements("accommodation") select c;
int AccomodationCount = Accommodations.Count();
int AccomodationIndex = 0;
foreach (var accommodation in Accommodations)
{
AccomodationIndex++;
var AccCode = accommodation.Element("code").Value;
try
{
Accommodation a = ih.Accommodations.Where(x=>x.code == AccCode).SingleOrDefault();
bool newAccommodation = a == null ? true : false;
a = !newAccommodation ? a :
new Accommodation
{
code = accommodation.Element("code") == null ? null : accommodation.Element("code").Value,
name = accommodation.Element("name") == null ? null : accommodation.Element("name").Value,
country = accommodation.Element("country") == null ? null : accommodation.Element("country").Value,
region = accommodation.Element("region") == null ? null : accommodation.Element("region").Value,
place = accommodation.Element("place") == null ? null : accommodation.Element("place").Value,
zip = accommodation.Element("zip") == null ? null : accommodation.Element("zip").Value,
type = accommodation.Element("type") == null ? null : accommodation.Element("type").Value,
quality = accommodation.Element("quality") == null ? (byte?)null : Convert.ToByte(accommodation.Element("quality").Value),
details = accommodation.Element("details") == null ? null : accommodation.Element("details").Value,
brand = accommodation.Element("brand") == null ? null : accommodation.Element("brand").Value,
pax = accommodation.Element("pax") == null ? (double?)null : Convert.ToDouble(accommodation.Element("pax").Value),
sqm = accommodation.Element("sqm") == null ? (double?)null : Convert.ToDouble(accommodation.Element("sqm").Value),
floor = accommodation.Element("floor") == null ? (double?)null : Convert.ToDouble(accommodation.Element("floor").Value),
rooms = accommodation.Element("rooms") == null ? (double?)null : Convert.ToDouble(accommodation.Element("rooms").Value),
bedrooms = accommodation.Element("bedrooms") == null ? (double?)null : Convert.ToDouble(accommodation.Element("bedrooms").Value),
toilets = accommodation.Element("toilets") == null ? (double?)null : Convert.ToDouble(accommodation.Element("toilets").Value),
bathrooms = accommodation.Element("bathrooms") == null ? (double?)null : Convert.ToDouble(accommodation.Element("bathrooms").Value),
lat = accommodation.Element("geodata") == null || accommodation.Element("geodata").Element("lat") == null ? null : accommodation.Element("geodata").Element("lat").Value,
lng = accommodation.Element("geodata") == null || accommodation.Element("geodata").Element("lng") == null ? null : accommodation.Element("geodata").Element("lng").Value,
LastUpdated = DateTime.Now
};
foreach (var attribute in accommodation.Elements("attributes").Elements("attribute").Select(x=>x.Value))
{
Attribute at = ih.Attributes.Where(x => x.name == attribute).SingleOrDefault();
a.Attributes.Add(at);
}
if (newAccommodation)
{
ih.Accommodations.Add(a);
}
else
{
ih.Entry(ih.Accommodations.Where(x => x.code == a.code).SingleOrDefault()).CurrentValues.SetValues(a);
ih.Entry(ih.Accommodations.Where(x => x.code == a.code).SingleOrDefault()).State = System.Data.EntityState.Modified;
}
ih.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
ih.SaveChanges();
}
このコードを実行した後、SQL で次を実行します。
select COUNT(*) from Accommodations
select COUNT(*)from Attributes
select COUNT(*)from AccommodationAttributes
しかし、2 つのテーブルにエントリが表示されますが、リンク テーブルには 0 行が含まれています。
オブジェクトをコンテキストにアタッチしたり、変更されたオブジェクトであることを暗黙的に指定したりするなど、他のバリエーションを試しました。
このコードが実行されるまでに、属性は既にデータベースに挿入されていると確信していますが、宿泊施設は挿入または更新のいずれかです。
アップデート
さらに調査したところ、新しい宿泊施設を追加すると機能するようですが、宿泊施設がすでにデータベースにあり、新しい属性を追加しただけでは失敗します。私の場合、開発の過程で最初に宿泊施設を追加し、開発の後の段階で属性をインポートするプロセスを作成しました。そのため、宿泊施設と属性の両方が既にデータベースにある場合に、関係を更新する方法を見つける必要があります。私はあなたの考えを聞きたいと思っています。
ヤニス