2013-04-13 37 views
1

我有一些问题。这是数据库结构:级联添加/更新树(父/子)数据

CREATE TABLE [EvaluationProcess].[CriteriaHeader](
    [CriteriaHeader_No] [uniqueidentifier] NOT NULL, 
    [CriteriaHeader_Type] [int] NOT NULL, 
    [CriteriaHeader_Name] [nvarchar](128) NOT NULL, 
    [CriteriaHeader_Description] [nvarchar](256) NULL, 
    [CriteriaHeader_MaxScore] [int] NOT NULL, 
    [CriteriaHeader_MinScore] [int] NOT NULL, 
    [CriteriaHeader_ScoreStep] [int] NOT NULL, 
    [CriteriaHeader_IsCountedResult] [bit] NOT NULL, 
    [CriteriaHeader_IsBlocked] [bit] NOT NULL, 
    [OwnedOrganisationID] [uniqueidentifier] NULL, 
    [ModifyUser] [uniqueidentifier] NULL, 
    [ModifyDate] [datetime] NULL, 
    [TimeStamp] [timestamp] NULL, 
CONSTRAINT [PK_Criteria] PRIMARY KEY CLUSTERED 
(
    [CriteriaHeader_No] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_No] DEFAULT (newsequentialid()) FOR [CriteriaHeader_No] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_Type] DEFAULT ((0)) FOR [CriteriaHeader_Type] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_MaxScore_1] DEFAULT ((5)) FOR [CriteriaHeader_MaxScore] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_MinScore_1] DEFAULT ((0)) FOR [CriteriaHeader_MinScore] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_ScoreStep_1] DEFAULT ((1)) FOR [CriteriaHeader_ScoreStep] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_IsCountedResult] DEFAULT ((0)) FOR [CriteriaHeader_IsCountedResult] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_Criteria_IsBlocked] DEFAULT ((0)) FOR [CriteriaHeader_IsBlocked] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaHeader] ADD CONSTRAINT [DF_Criteria_ModifyDate] DEFAULT (getdate()) FOR [ModifyDate] 
GO 

CREATE TABLE [EvaluationProcess].[CriteriaLine](
    [CriteriaLine_No] [uniqueidentifier] NOT NULL, 
    [CriteriaLine_ParentID] [uniqueidentifier] NULL, 
    [CriteriaLine_CriteriaHeaderID] [uniqueidentifier] NULL, 
    [CriteriaLine_Text] [nvarchar](128) NOT NULL, 
    [CriteriaLine_Description] [nvarchar](512) NULL, 
    [OwnedOrganisationID] [uniqueidentifier] NULL, 
    [ModifyUser] [uniqueidentifier] NULL, 
    [ModifyDate] [datetime] NULL, 
    [TimeStamp] [timestamp] NULL, 
CONSTRAINT [PK_CriteriaList] PRIMARY KEY CLUSTERED 
(
    [CriteriaLine_No] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [EvaluationProcess].[CriteriaLine] ADD CONSTRAINT [DF_CriteriaList_CriteriaList_No] DEFAULT (newsequentialid()) FOR [CriteriaLine_No] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaLine] ADD CONSTRAINT [DF_CriteriaList_ModifyDate] DEFAULT (getdate()) FOR [ModifyDate] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaLine] WITH CHECK ADD CONSTRAINT [FK_CriteriaLine_CriteriaLine] FOREIGN KEY([CriteriaLine_CriteriaHeaderID]) 
REFERENCES [EvaluationProcess].[CriteriaHeader] ([CriteriaHeader_No]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaLine] CHECK CONSTRAINT [FK_CriteriaLine_CriteriaLine] 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaLine] WITH CHECK ADD CONSTRAINT [FK_CriteriaLine_CriteriaLine1] FOREIGN KEY([CriteriaLine_ParentID]) 
REFERENCES [EvaluationProcess].[CriteriaLine] ([CriteriaLine_No]) 
GO 

ALTER TABLE [EvaluationProcess].[CriteriaLine] CHECK CONSTRAINT [FK_CriteriaLine_CriteriaLine1] 
GO 

我使用的EntityFramework 5.这是一个新增/更新功能

public override bool InsertOrUpdate(object[] _BaseEntityClasses, string _RoleName, 
            System.Nullable<Guid> _LoginUserID, 
             System.Nullable<System.Guid> _OrganisationID, bool? IsModified = null) 
{ 
    using (Evaluation_SystemConection EvaluationDBContext = new Evaluation_SystemConection()) 
    { 
     try 
     { 
      EvaluationDBContext.Configuration.AutoDetectChangesEnabled = false; 

      IEnumerable<CriteriaHeader> _BaseEntityClassesList = _BaseEntityClasses.Cast<CriteriaHeader>(); 

      foreach (var OneItem in _BaseEntityClassesList) 
      { 
       if (OneItem.CriteriaLines != null) 
       { 
        foreach (var OneLine in OneItem.CriteriaLines) 
        { 
         if (OneLine.CriteriaLine_No == Guid.Empty) 
          OneLine.CriteriaLine_CriteriaHeaderID = OneItem.CriteriaHeader_No; 

         EvaluationDBContext.CriteriaLines.Attach(OneLine); 


         EvaluationDBContext.Entry(OneLine).State = OneLine.CriteriaLine_No == Guid.Empty ? EntityState.Added : EntityState.Modified; 

        } 

       } 

       EvaluationDBContext.CriteriaHeaders.Add(OneItem); 

       EvaluationDBContext.Entry(OneItem).State = OneItem.CriteriaHeader_No == Guid.Empty ? EntityState.Added : EntityState.Modified; 

       if (EvaluationDBContext.SaveChanges() <= 0) 
        return false; 
      } 

      return true; 
     } 
     catch (Exception Ex) 
     { 
      ErrorMessage.Add(""); 

      ErrorMessage.Add((Ex.InnerException != null) ? Ex.InnerException.Message : Ex.Message); 

      return false; 
     } 
     finally 
     { 
      EvaluationDBContext.Configuration.AutoDetectChangesEnabled = true; 
     } 
    } 

} 

和生成的POCO类

public partial class CriteriaHeader 
{ 
    public CriteriaHeader() 
    { 
     this.CriteriaLines = new HashSet<CriteriaLine>(); 
    } 

    public System.Guid CriteriaHeader_No { get; set; } 
    public int CriteriaHeader_Type { get; set; } 
    public string CriteriaHeader_Name { get; set; } 
    public string CriteriaHeader_Description { get; set; } 
    public int CriteriaHeader_MaxScore { get; set; } 
    public int CriteriaHeader_MinScore { get; set; } 
    public int CriteriaHeader_ScoreStep { get; set; } 
    public bool CriteriaHeader_IsCountedResult { get; set; } 
    public bool CriteriaHeader_IsBlocked { get; set; } 
    public Nullable<System.Guid> OwnedOrganisationID { get; set; } 
    public Nullable<System.Guid> ModifyUser { get; set; } 
    public Nullable<System.DateTime> ModifyDate { get; set; } 
    public byte[] TimeStamp { get; set; } 

    public virtual ICollection<CriteriaLine> CriteriaLines { get; set; } 
} 

public partial class CriteriaLine 
{ 
    public CriteriaLine() 
    { 
     this.CriteriaLine1 = new HashSet<CriteriaLine>(); 
    } 

    public System.Guid CriteriaLine_No { get; set; } 
    public Nullable<System.Guid> CriteriaLine_ParentID { get; set; } 
    public Nullable<System.Guid> CriteriaLine_CriteriaHeaderID { get; set; } 
    public string CriteriaLine_Text { get; set; } 
    public string CriteriaLine_Description { get; set; } 
    public Nullable<System.Guid> OwnedOrganisationID { get; set; } 
    public Nullable<System.Guid> ModifyUser { get; set; } 
    public Nullable<System.DateTime> ModifyDate { get; set; } 
    public byte[] TimeStamp { get; set; } 

    public virtual CriteriaHeader CriteriaHeader { get; set; } 
    public virtual ICollection<CriteriaLine> CriteriaLine1 { get; set; } 
    public virtual CriteriaLine CriteriaLine2 { get; set; } 
} 

数据没有插入或更新在CriteriaList以上1级以上。

我做错了什么?

回答

0

首先,您应该尽量避免更改AutoDetectChangesEnabled。当你使用这个功能时,你必须彻底理解它的功能(而不是)。所以首先要做的就是不要碰AutoDetectChangesEnabled。它看起来像你的方法可以没有它的工作。如果没有,请随时告诉发生了什么,以便我们可以尝试处理它。 (我怀疑你会试图通过更改AutoDetectChangesEnabled来防止出现一些问题)。

你可以考虑使用实体框架自己的AddOrUpdate method。那么,你有

EvaluationDBContext.CriteriaHeaders.Add(OneItem); 
EvaluationDBContext.Entry(OneItem).State = OneItem.CriteriaHeader_No == Guid.Empty ? EntityState.Added : EntityState.Modified; 

你可以做

EvaluationDBContext.CriteriaHeaders.AddOrUpdate(OneItem); 

(同样与CriteriaLines)。

但是它每次记录都需要往返数据库以查看是否应该插入或更新。

代码中存在更多问题。

  • 命名约定(如_BaseEntityClasses,惯例是baseEntityClasses
  • ,则不应使用object[]作为输入参数,但使用泛型:。InsertOrUpdate<T>(IEnumerable<T> baseEntityClasses, ...
  • 你似乎有一些外部ErrorMessage名单,这是节目。即你的方法的状态方法有副作用,这可能是很难说哪里ErrorMessage受到影响,当它应该被清除或报告。
  • 你吞下任何异常。这是没有真正的异常处理。只是重新掷他们和韩在适当的时候使用它们。
  • 不要只返回一个布尔值。特别是当你返回false这是毫无意义的。例如,您可以返回受影响的行数。与重新抛出异常一起,消费者将从您的方法获得更多信息,而不仅仅是布尔值。
+0

Thanks for Answer AutoDetectChangesEnabled = false。我用于提高性能操作。这是真的吗? – PaataPP

+0

当然,它会提高性能(一点),因为变化跟踪器不那么繁忙,但有副作用,你应该清楚。只有在表现不可接受时才使用它,并且没有其他方法可以改进它。 –