私は WCF RIA Services を初めて使用し、LightSwitch を使用して 4 か月ほどになります。LightSwitch アプリケーション全体でルックアップ テーブルを編集するために使用する汎用画面を作成しました。これは主に、さまざまなエンティティ セットで動的に使用できる汎用画面を作成する方法を学習するためです。
画面は非常にシンプルです。
次のような引数で開かれます:
Application.ShowLookupTypesList("StatusTypes", "StatusTypeId");
データベース内のルックアップ テーブルのエンティティ セットに対応します。
これが私の WCF RIA サービス コードです。
using System.Data.Objects.DataClasses;
using System.Diagnostics;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Server;
namespace WCF_RIA_Project
{
public class LookupType
{
[Key]
public int TypeId { get; set; }
public string Name { get; set; }
}
public static class EntityInfo
{
public static Type Type;
public static PropertyInfo Key;
public static PropertyInfo Set;
}
public class WCF_RIA_Service : LinqToEntitiesDomainService<WCSEntities>
{
public IQueryable<LookupType> GetLookupTypesByEntitySet(string EntitySetName, string KeyName)
{
EntityInfo.Set = ObjectContext.GetType().GetProperty(EntitySetName);
EntityInfo.Type = EntityInfo.Set.PropertyType.GetGenericArguments().First();
EntityInfo.Key = EntityInfo.Type.GetProperty(KeyName);
return GetTypes();
}
[Query(IsDefault = true)]
public IQueryable<LookupType> GetTypes()
{
var set = (IEnumerable<EntityObject>)EntityInfo.Set.GetValue(ObjectContext, null);
var types = from e in set
select new LookupType
{
TypeId = (int)EntityInfo.Key.GetValue(e, null),
Name = (string)EntityInfo.Type.GetProperty("Name").GetValue(e, null)
};
return types.AsQueryable();
}
public void InsertLookupType(LookupType lookupType)
{
dynamic e = Activator.CreateInstance(EntityInfo.Type);
EntityInfo.Key.SetValue(e, lookupType.TypeId, null);
e.Name = lookupType.Name;
dynamic set = EntityInfo.Set.GetValue(ObjectContext, null);
set.AddObject(e);
}
public void UpdateLookupType(LookupType currentLookupType)
{
var set = (IEnumerable<EntityObject>)EntityInfo.Set.GetValue(ObjectContext, null);
dynamic modified = set.FirstOrDefault(t => (int)EntityInfo.Key.GetValue(t, null) == currentLookupType.TypeId);
modified.Name = currentLookupType.Name;
}
public void DeleteLookupType(LookupType lookupType)
{
var set = (IEnumerable<EntityObject>)EntityInfo.Set.GetValue(ObjectContext, null);
var e = set.FirstOrDefault(t => (int)EntityInfo.Key.GetValue(t, null) == lookupType.TypeId);
Debug.Assert(e.EntityState != EntityState.Detached, "Entity was in a detached state.");
ObjectContext.ObjectStateManager.ChangeObjectState(e, EntityState.Deleted);
}
}
}
実行中の画面から項目をリストに追加して保存し、編集して再保存すると、 「別のユーザーがこのレコードを削除しました」というデータ競合が発生します。
保存後にクエリをリロードすることでこれを回避できますが、扱いにくいです。
同じ名前のアイテムを削除して保存し、readd して保存すると、データを保存できなくなります。「コンテキストは、同じリソース URI を持つ別のエンティティを既に追跡しています。」
これらの問題は両方とも、WCF RIA サービスを使用している一般的な画面にのみ影響します。特定のデータベース エンティティの ListDetail 画面を作成しても、問題はありません。いくつかのロジックが欠けているようですが、アイデアはありますか?