私は本当に理解できない厄介な問題を抱えています。
基本的に私は次のように定義されたDbContextを持っています
public interface ISettingsContext : IDisposable
{
IDbSet<Site> Sites { get; }
IDbSet<SettingGroup> Groups { get; }
IDbSet<SettingProperty> Properties { get; }
int SaveChanges();
}
public class SettingsContext : DbContext, ISettingsContext
{
public SettingsContext(string connectionStringName) : base(connectionStringName)
{
Sites = Set<Site>();
Groups = Set<SettingGroup>();
Properties = Set<SettingProperty>();
}
public SettingsContext() : this("DefaultTestConnectionString") { }
public IDbSet<Site> Sites { get; private set; }
public IDbSet<SettingGroup> Groups { get; private set; }
public IDbSet<SettingProperty> Properties { get; private set; }
#region Model Creation
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
MapSite(modelBuilder.Entity<Site>());
MapGroup(modelBuilder.Entity<SettingGroup>());
MapProperty(modelBuilder.Entity<SettingProperty>());
MapValue(modelBuilder.Entity<SiteSettingValue>());
MapXmlValue(modelBuilder.ComplexType<XmlValue>());
MapXmlType(modelBuilder.ComplexType<XmlTypeDescriptor>());
}
private void MapXmlType(ComplexTypeConfiguration<XmlTypeDescriptor> complexType)
{
complexType.Ignore(t => t.Type);
}
private void MapXmlValue(ComplexTypeConfiguration<XmlValue> complexType)
{
complexType.Ignore(t => t.Value);
}
private void MapValue(EntityTypeConfiguration<SiteSettingValue> entity)
{
entity.HasKey(k => new { k.PropertyId, k.SiteId }).ToTable("SiteValues", "settings");
entity.Property(k => k.PropertyId).HasColumnName("FKPropertyID");
entity.Property(k => k.SiteId).HasColumnName("FKSiteID");
entity.Property(k => k.Value.RawData).HasColumnName("Value").IsMaxLength();
entity.HasRequired(k => k.Site).WithMany(s => s.Settings).HasForeignKey(k => k.SiteId);
entity.HasRequired(k => k.Property).WithMany().HasForeignKey(k => k.PropertyId);
}
private void MapProperty(EntityTypeConfiguration<SettingProperty> entity)
{
entity.HasKey(k => k.Id).ToTable("Properties", "settings");
entity.Property(k => k.Id);
entity.Property(k => k.Name);
entity.Property(k => k.GroupId).HasColumnName("FKGroupID");
entity.Property(k => k.PropertyDescriptor.RawData).HasColumnName("TypeDescriptor").IsMaxLength();
entity.Property(k => k.DefaultValue.RawData).HasColumnName("DefaultValue").IsMaxLength();
entity.HasRequired(k => k.Group).WithMany(k => k.Properties).HasForeignKey(k => k.GroupId);
}
private void MapGroup(EntityTypeConfiguration<SettingGroup> entity)
{
entity.HasKey(k => k.Id).ToTable("Groups", "settings");
entity.Property(k => k.Id);
entity.Property(k => k.Name);
entity.HasMany(k => k.Properties).WithRequired(k => k.Group).HasForeignKey(k => k.GroupId);
}
private void MapSite(EntityTypeConfiguration<Site> entity)
{
entity.HasKey(k => k.Id).ToTable("Sites", "site");
entity.Property(k => k.Id);
entity.Property(k => k.Domain);
}
#endregion
}
いくつかのテストを行っていたので、IoCとDIを気にせずにこのコンテキストで作業を開始したので、具象クラス自体に対して直接作業しました。
だから私はこのクエリを書きました:
public class SiteSettingsLoader : ILoader<SiteSettingsModel, int> {
...
var qSiteValues = from site in context.Sites
let settings = site.Settings
select new
{
SiteId = site.Id,
Settings = from value in settings
join property in context.Properties on value.PropertyId equals property.Id into props
from property in props
select new
{
PropertyId = property.Id,
Name = property.Name,
GroupId = property.GroupId,
Value = value.Value,
CanBeInherited = property.CanBeInherited
}
};
そして、すべてがうまくいきました。問題は、実際のタイプではなく、実装するインターフェイスとしてコンテキストを渡し始めたときに始まりました。
using (ISettingsContext context = new SettingsContext())
using (SiteSettingsLoader loader = new SiteSettingsLoader(context))
{
SiteSettingsStore store = new SiteSettingsStore(loader);
dynamic settings = store.GetItem(1);
}
これはエラーです
タイプ'Settings.Entities.SettingProperty'の定数値を作成できません。このコンテキストでは、プリミティブ型('Int32、String、Guid'など)のみがサポートされます。
どうしてそれは可能ですか?マイクロソフトはリフレクションで汚いトリックをしましたか?
編集:XmlValueとXmlTypeDescriptorはどちらも、XMLフィールドのコンテンツを適切なオブジェクトに自動的に読み込むために使用する次のインターフェイスの実装です。
public interface IXmlProperty
{
string RawData { get; set; }
void Load(string xml);
XDocument ToXml();
}
基本的に、フィールドのコンテンツをRawDataプロパティにマップします。セッターとゲッターでは、データベースのXMLを含む文字列を解析/生成します。私はそれが醜いトリックであることを知っていますが、それは機能し、仕事を成し遂げます。