Вот фрагмент рабочего кода, который может обновлять разные таблицы во время выполнения из разных контекстов без использования отражения.
namespace DemoContexts
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
public interface IThing
{
int Id { get; set; }
int Status { get; set; }
}
public class FirstPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Foo { get; set; }
}
public class SecondPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Bar { get; set; }
}
public class FirstContext : DbContext
{
public FirstContext() : base("FirstContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
public class SecondContext : DbContext
{
public SecondContext() : base("SecondContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
class Program
{
static void Main(string[] args)
{
int contextType = 1;
int thingType = 1;
DbContext db = RunTimeCreatedContext(contextType);
IQueryable<IThing> collection = RunTimeCreatedCollection(db, thingType);
UpdateRuntimeDeterminedThings(db, collection, 1);
Console.ReadLine();
}
public static void UpdateRuntimeDeterminedThings(DbContext db,
IQueryable<IThing> collection,
int formId)
{
var querySet = collection.Where(p => p.Id == formId).ToList();
foreach (var result in querySet)
{
result.Status = 0;
}
db.SaveChanges();
}
static DbContext RunTimeCreatedContext(int contextType)
{
if (contextType == 0)
{
return new FirstContext();
}
else
{
return new SecondContext();
}
}
static IQueryable<IThing> RunTimeCreatedCollection(DbContext db, int thingType)
{
if (thingType == 0)
{
return db.Set(typeof(FirstPersonThing)) as IQueryable<IThing>;
}
else
{
return db.Set<SecondPersonThing>();
}
}
}
}
Первое, что нужно отметить, это то, что все это статически типизировано, поэтому для выполнения общего запроса к объектам разных типов эти объекты должны иметь общие сигнатуры свойств, и это концептуально выражается в интерфейсе IThing.
Второе, на что следует обратить внимание, это то, как генерируется IQueryable. Он создается с помощью DbContext.Set Method (Type) в первый экземпляр (для FirstPersonThings), он создается с помощью DbContext.Set<TEntity> Method во втором экземпляре. Первый использует тип, определенный во время выполнения, и требует приведения (но может быть полезно использовать проходящие типы во время выполнения), второй использует дженерики, а типы определяются во время компиляции. Очевидно, существует ряд других способов, которыми эта функция может работать.
Наконец, метод UpdateRuntimeDeterminedThings работает, потому что он использует свойства и методы, которые являются общими для всех типов (либо с базовыми типами/наследованием, либо с помощью реализации интерфейсов).
Ничто из этого на самом деле не является динамическим программированием (что возможно при использовании динамического типа), и я использовал термин «определяемое время выполнения», а не «динамическое», чтобы описать, как это работает.
person
AlexC
schedule
11.11.2014
IdиStatus? Ваша проблема меньше связана с самим LINQ, а больше с тем фактом, что С# является статически типизированным языком - вы не можете (легко) делать то, что хотите, без некоторого базового типа, представляющего общие свойства, которые вы хотите использовать в своем универсальном запрос. - person rsenna   schedule 10.11.2014DbContextне помогает, даже учитывая, что есть способы получить текущий контекст из данного объекта. - person rsenna   schedule 10.11.2014