Linq to SQL:从数据上下文中排除要插入的列

时间:2014-07-19 19:09:48

标签: c# linq-to-sql

我现在对这个话题感到困惑,我会很感激如何处理我的问题的提示或解释。

我正在尝试使用ORM将我的对象映射到数据库。我有一个母对象,有几个子元素和子元素。当我将母元素(位置)添加到我的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。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我对Linq 2 SQL的一种厌恶是它在以下情况下自动标记要插入的实体:

  1. 您从数据上下文中指定一个具有关联对象的新实体,而不显式调用InsertOnSubmit
  2. 或者就像您经历过的那样,当您设置单个对象进行插入时,它会自动遍历实体树并标记插入的对象
  3. 在DB上设置约束并不能真正解决问题,因为数据上下文仍然会尝试插入实体并像您所经历的那样抛出异常。最好阻止Linq 2 SQL上下文插入这些对象。

    Todo我为InsertOnSubmitExplicitly类创建了一个扩展方法Table,在您明确设置要插入的实体时,您可能会发现这些方法非常有用。对于那些您不想插入的人(即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点所述,如果您创建一个新实体并从数据上下文为其分配关联实体,它将自动将其标记为插入。但是,就像我在我的解决方案中实现的那样,您可以为数据上下文创建一个显式丢弃所有插入的扩展方法。