所以我不确定你是否可以这样做,但是如果可以的话我想避免使用SQL字符串。我想用Linq / DbContexts做的事情可以通过SQL轻松完成:
string sql = "UPDATE " + tableName + " SET Status=0 WHERE Id=" + formId.ToString();
我可以轻松地将它放入一个循环中,其中tableName和formId是动态给定的,并且执行没有问题。
我有多个DbContexts,所以我不知道有什么方法可以做这样的事情:
var db = new *dynamicallyChosenContext*()
var query = from p in db.*dynamicallyChosenAlso*
where p.Id == formId
select p;
foreach (var result in query)
{
result.Status = 0;
}
db.SaveChanges()
感谢您的帮助!
答案 0 :(得分:1)
这是一段工作代码,可以在运行时从不同的上下文更新不同的表而不使用反射。
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方法可以正常工作,因为它使用了跨类型共享的属性和方法(基类型/继承或接口实现)。
这些实际上都不是动态编程(可以使用动态类型),我使用术语运行时确定而不是动态来描述它是如何工作的。
答案 1 :(得分:0)
函数式编程中有一种称为Currying的技术,您可以根据需要传递尽可能多的参数,以便能够访问它们。 这是一个例子:http://blogs.msdn.com/b/sriram/archive/2005/08/07/448722.aspx
P.S:你可以使用currying函数迭代你的DBContexts。
答案 2 :(得分:0)
如果你想使用'code'而不是sql字符串,我认为你必须使用反射。这就是C#的工作原理......这就是你可以做到的:
using System;
using System.Data.Entity;
using System.Linq;
public class TestContext : DbContext
{
public DbSet<Box> Boxes { get; set; }
public DbSet<Thing> Things { get; set; }
}
public abstract class Base
{
public int Id { get; set; }
}
public class Box : Base
{
public string Title { get; set; }
}
public class Thing : Base
{
public string Name { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var db = new TestContext();
DoIt(GetPropValue(db, "Boxes") as IQueryable<Base>);
DoIt(GetPropValue(db, "Things") as IQueryable<Base>);
}
private static void DoIt(IQueryable<Base> b)
{
Console.WriteLine(
b.Single(t => t.Id == 1).Id);
}
private static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
}
显然,无论你需要什么,你都可以将字符串放在列表等中。