Linq to SQL:从数据上下文中排除要插入的列
本文关键字:排除 插入 上下文 SQL to 数据 Linq | 更新日期: 2023-09-27 18:13:45
我被这个话题困了一段时间了,我希望你能给我一个提示或解释一下如何解决我的问题。
我正在尝试实现ORM来映射我的对象与数据库。我有一个带有几个子元素和子元素的母对象。当我将母元素(Position)添加到DataContext时,所有的子元素也被添加。向数据库插入一个新对象可以正常工作。
class Position{
public BE be { get; set; }; // Child element
// and so on...
}
class BE{
[XmlIgnore, Column]
public Nullable<int> Rueckstrom1Id { get; set; }
[XmlElement(typeof(Rueckstrom)), Association(Storage = "rueckstrom1", ThisKey = "Rueckstrom1Id", IsForeignKey = true)]
public Rueckstrom Rueckstrom1 {
get { return this.rueckstrom1.Entity; }
set { this.rueckstrom1.Entity = value; }
}
[XmlIgnore, Column]
public Nullable<int> Rueckstrom2Id { get; set; }
[XmlElement(typeof(Rueckstrom)), Association(Storage = "rueckstrom2", ThisKey = "Rueckstrom2Id", IsForeignKey = true)]
public Rueckstrom Rueckstrom2 {
get { return this.rueckstrom2.Entity; }
set { this.rueckstrom2.Entity = value; }
}
// and so on...
}
class Rueckstrom{
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "Int NOT NULL IDENTITY(1,1)")]
public int Id {
get { return this.id; }
set { this.id = value; }
}
[Column(DbType = "Decimal(8,2)")]
public decimal Sek {
get { return this.sek; }
set { this.sek = value; }
}
// and so on...
}
事情是这样的:当我将"Position"元素添加到数据上下文中,比如
dataContext.Position.InsertOnSubmit(position);
所有子元素,如"Rueckstrom1", "Rueckstrom2",…也被添加到上下文中,并最终被插入到数据库中
db.SubmitChanges ();我想防止这种插入,以防我总共7个"Rueckstrom"元素中有一个元素的"Sek"属性值为0。
由于Id还没有由数据库生成(因此是0),因为它是一个全新的对象,我不知道如何避免在SubmitChanges()上插入特定的子元素(类型为"Rueckstrom")。
我知道如果"Sek"属性为0,我可以将整个"Rueckstrom"对象设置为NULL,但是由于我在程序中的实现,所有7个"Rueckstrom"子对象总是非NULL。
任何想法?
我最讨厌的一个Linq 2 SQL是它自动标记实体插入:
- 不需要显式调用InsertOnSubmit ,就可以从数据上下文中为一个带有关联对象的新实体赋值
- 或者像你所经历的那样,当你设置要插入的单个对象时,它会自动遍历实体树并将其标记为要插入的
在DB上放置约束并不能真正解决问题,因为数据上下文仍然会尝试插入实体并抛出异常,就像您所经历的那样。最好是防止Linq 2 SQL上下文插入这些对象。
为此,我为Table
类创建了一个扩展方法InsertOnSubmitExplicitly
,当您显式设置要插入的实体时,您可能会发现它很有用。对于那些你不想插入的(即Sek=0),你只需不调用这个方法或默认的InsertOnSubmit
方法。
解决方案:
public static void InsertOnSubmitExplicitly<TEntity>(this Table<TEntity> table, TEntity obj)
where TEntity : class
{
ChangeSet preSet = table.Context.GetChangeSet();
if (preSet == null)
throw new Exception("Unable to retrieve change set on data context before insert");
table.InsertOnSubmit(obj);
ChangeSet postSet = table.Context.GetChangeSet();
if (postSet == null)
throw new Exception("Unable to retrieve change set on data context after insert");
var markAsDeleted = (from post in postSet.Inserts.Where(n => !ReferenceEquals(n, obj))
join pre in preSet.Inserts on post equals pre into temp1
from t1 in temp1.DefaultIfEmpty()
where t1 == null
select post);
foreach (var entity in markAsDeleted)
table.Context.GetTable(entity.GetType()).DeleteOnSubmit(entity);
}
用法:
dataContext.Position.InsertOnSubmitExplicitly(position);
注意:
如上面第1点所述,如果您创建一个新实体并从数据上下文中为其分配一个关联实体,它将自动将其标记为要插入。但是,就像我在解决方案中实现的那样,您可以为数据上下文创建一个扩展方法,该方法显式地丢弃所有插入。