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 to SQL:从数据上下文中排除要插入的列

我最讨厌的一个Linq 2 SQL是它自动标记实体插入:

  1. 不需要显式调用InsertOnSubmit
  2. ,就可以从数据上下文中为一个带有关联对象的新实体赋值
  3. 或者像你所经历的那样,当你设置要插入的单个对象时,它会自动遍历实体树并将其标记为要插入的

在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点所述,如果您创建一个新实体并从数据上下文中为其分配一个关联实体,它将自动将其标记为要插入。但是,就像我在解决方案中实现的那样,您可以为数据上下文创建一个扩展方法,该方法显式地丢弃所有插入。