对模糊问题道歉。这是:我有一个由LINQ to SQL创建的表对象。我正在将条目从一个表复制到一个“存档”表,其中包含原始列的所有列,以及一些额外的列。
迭代遍历每个对象并手动定义映射感觉很草率:
foreach (oldTable in dbContextOldTables)
{
var newTable = new NewTable();
newTable.TableID = oldTable.ID;
newTable.Title = oldTable.Title;
... (repeat for twenty columns)
newTable.ColumnThatIsntInOldTable = "Data that will be the same for every row";
dbContext.NewTables.InsertOnSubmit(newTable);
}
dbContext.SubmitChanges();
有一种聪明的方法吗?
答案 0 :(得分:2)
考虑使用dbConext.ExecuteCommand()
函数直接执行SQL,例如:
ctx.ExecuteCommand("INSERT INTO backup SELECT * FROM original");
或者你可以使用InsertAllOnSubmit,例如:
var entries = dbContextOldTables.AsEnumerable().Select(x => new NewTable() { /* mapping */ });
dbContext.NewTables.InsertAllOnSubmit(entries);
修改2010-04-09:
将IQueryable
传递到InsertAllOnSubmit
构建新项目(即new NewTable()
)失败的原因如下(source):
此检查已添加,因为它应该从一开始就存在并且丢失了。手动构建实体实例作为投影会使用可能格式错误的对象污染缓存,从而导致程序员和我们的许多错误报告混乱。此外,预测实体是应该在缓存中还是根本不进行跟踪是不明确的。实体的使用模式是它们是在查询之外创建的,并通过DataContext插入表中,然后通过查询检索,而不是由查询创建。
因此,错误发生是因为IQueryable
正在尝试通过执行返回select指定的项目的SQL查询来在缓存上创建项目。使用IQueryable
函数将IEnumberable
转换为AsEnumerable()
会破坏SQL生成。因此生成的查询只选择项目(即SQL不执行映射),并且新项目的构造在Linq to SQL逻辑之外完成。
为了确保我使用Northwind DB测试了该方法,我在其中使用以下代码创建了Categories表的副本:
using (var ctx = new NorthwindDataContext()) {
var categories = ctx.Categories;
var catcopy = categories.Select(x => new CategoriesBackup() {
CategoryID = x.CategoryID,
CategoryName = x.CategoryName,
Description = x.Description,
Picture = x.Picture
});
//ctx.CategoriesBackups.InsertAllOnSubmit(catcopy); // THIS DOES NOT WORK
var catcopy2 = categories.AsEnumerable().Select(x => new CategoriesBackup() {
CategoryID = x.CategoryID,
CategoryName = x.CategoryName,
Description = x.Description,
Picture = x.Picture
});
ctx.CategoriesBackups.InsertAllOnSubmit(catcopy2); // THIS WORKS
}
答案 1 :(得分:1)
您可以使用Automapper(http://automapper.codeplex.com/)或一些非常简单的反射代码将数据从一个对象复制到另一个对象,这样您就不需要手动写出每个字段。
例如,使用界面确保它们匹配: -
public interface IShared
{
int Prop1 {get; set;}
string Prop2 {get; set;}
}
public class A : IShared
{
public int Prop1 {get; set;}
public string Prop2 {get; set;}
}
public class B : IShared
{
public int Prop1 {get; set;}
public string Prop2 {get; set;}
}
static void Main(string[] args)
{
A A = new A(){ Prop1 = 1, Prop2 = "2" };
B B = new B();
var properties = typeof(IShared).GetProperties();
foreach (var prop in properties)
{
object currentValue = prop.GetValue(A, null);
prop.SetValue(B, currentValue, null);
}
Console.WriteLine("B = " + B.Prop1 + " " + B.Prop2);
Console.ReadKey();
注意:这不会处理数组,您可以扩展它来执行此操作,或者您可以只使用自动映射。