C# 如何找到违反约束的列?
我有一个强类型数据集,它为空值抛出这个错误 System.Data.ConstraintException:未能启用约束。一个或多个 更多行包含违反非空、唯一或外键的值 限制。在System.Data.DataTable.EnableConstraints处 System.Data.DataTable.EndLoadData位于 System.Data.Common.DataAdapter.FillFromReaderDataSet数据集, DataTable DataTable、字符串srcTable、dataReader容器dataReader、, Int32 startRecord、Int32 maxRecords、DataColumn parentChapterColumn、, 对象parentChapterValue位于 System.Data.Common.DataAdapter.FillDataTable[]数据表, IDataReader数据读取器,Int32 startRecord,Int32 maxRecords位于 System.Data.Common.DbDataAdapter.FillInternalDataSet数据集, DataTable[]datatables,Int32 startRecord,Int32 maxRecords,字符串 srcTable,IDbCommand命令,CommandBehavior行为 System.Data.Common.DbDataAdapter.FillDataTable[]数据表,Int32 startRecord、Int32 maxRecords、IDbCommand、CommandBehavior System.Data.Common.DbDataAdapter.FillDataTable上的行为 数据表位于 Fruits.DataAccess.FruitsStableApters.FruitsettableAdapter.GetFruitsString 用户,字符串筛选器位于 Fruits.DataAccess.FruitsDataAccess.GetFruitsString用户,字符串 在Fruits.WebServices.External.Fruity.getfruitssString处过滤 滤器 所有列都填充了一行,我正在测试它C# 如何找到违反约束的列?,c#,sql-server-2008,stored-procedures,strongly-typed-dataset,C#,Sql Server 2008,Stored Procedures,Strongly Typed Dataset,我有一个强类型数据集,它为空值抛出这个错误 System.Data.ConstraintException:未能启用约束。一个或多个 更多行包含违反非空、唯一或外键的值 限制。在System.Data.DataTable.EnableConstraints处 System.Data.DataTable.EndLoadData位于 System.Data.Common.DataAdapter.FillFromReaderDataSet数据集, DataTable DataTable、字符串srcT
USE [FruitDataBase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Fruits](
[ID] [int] NOT NULL,
[CategoryID] [int] NOT NULL,
[Title] [nvarchar](255) NOT NULL,
[URL] [nvarchar](255) NOT NULL,
[Status] [nvarchar](70) NOT NULL,
[Description] [nvarchar](1024) NULL,
[User1] [nvarchar](50) NOT NULL,
[Date] [datetime] NOT NULL,
[User2] [nvarchar](50) NULL,
[Date2] [datetime] NULL,
[Impact] [nvarchar](255) NULL,
[Solution] [nvarchar](1024) NULL,
CONSTRAINT [PK_Fruits] PRIMARY KEY CLUSTERED
(
[ID] 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 [dbo].[Fruits] WITH CHECK ADD CONSTRAINT [FK_Fruits_Categories] FOREIGN KEY([CategoryID])
REFERENCES [dbo].[Categories] ([ID])
GO
ALTER TABLE [dbo].[Fruits] CHECK CONSTRAINT [FK_Fruits_Categories]
GO
问题是其中一个列名在数据集中不匹配,不确定是什么触发了它,但将列名与返回的列名匹配修复了该问题
我还使用了强类型数据集的预览数据功能,这帮助我解决了问题。数据集/数据表具有属性,可以获取有关错误的更多详细信息 因此,这些细节本身并不像你所想的那样是例外,这就是诀窍。看 样本:
catch (ConstraintException)
{
DataRow[] rowErrors = this.YourDataSet.YourDataTable.GetErrors();
System.Diagnostics.Debug.WriteLine("YourDataTable Errors:"
+ rowErrors.Length);
for (int i = 0; i < rowErrors.Length; i++)
{
System.Diagnostics.Debug.WriteLine(rowErrors[i].RowError);
foreach (DataColumn col in rowErrors[i].GetColumnsInError())
{
System.Diagnostics.Debug.WriteLine(col.ColumnName
+ ":" + rowErrors[i].GetColumnError(col));
}
}
}
您可以在代码中使用此方法。NET检查数据集,从而引发异常
public void CheckDataSet(DataSet dataSet)
{
Assembly assembly = Assembly.LoadFrom(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.dll");
Type type = assembly.GetType("System.Data.ConstraintEnumerator");
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(DataSet) });
object instance = ctor.Invoke(new object[] { dataSet });
BindingFlags bf = BindingFlags.Instance | BindingFlags.Public;
MethodInfo m_GetNext = type.GetMethod("GetNext", bf);
while ((bool)m_GetNext.Invoke(instance, null))
{
bool flag = false;
MethodInfo m_GetConstraint = type.GetMethod("GetConstraint", bf);
Constraint constraint = (Constraint) m_GetConstraint.Invoke(instance, null);
Type constraintType = constraint.GetType();
BindingFlags bfInternal = BindingFlags.Instance | BindingFlags.NonPublic;
MethodInfo m_IsConstraintViolated = constraintType.GetMethod("IsConstraintViolated", bfInternal);
flag = (bool)m_IsConstraintViolated.Invoke(constraint, null);
if (flag)
Debug.WriteLine("Constraint violated, ConstraintName: " + constraint.ConstraintName + ", tableName: " + constraint.Table);
}
foreach (DataTable table in dataSet.Tables)
{
foreach (DataColumn column in table.Columns)
{
Type columnType = column.GetType();
BindingFlags bfInternal = BindingFlags.Instance | BindingFlags.NonPublic;
bool flag = false;
if (!column.AllowDBNull)
{
MethodInfo m_IsNotAllowDBNullViolated = columnType.GetMethod("IsNotAllowDBNullViolated", bfInternal);
flag = (bool)m_IsNotAllowDBNullViolated.Invoke(column, null);
if (flag)
{
Debug.WriteLine("DBnull violated --> ColumnName: " + column.ColumnName + ", tableName: " + column.Table.TableName);
}
}
if (column.MaxLength >= 0)
{
MethodInfo m_IsMaxLengthViolated = columnType.GetMethod("IsMaxLengthViolated", bfInternal);
flag = (bool)m_IsMaxLengthViolated.Invoke(column, null);
if (flag)
Debug.WriteLine("MaxLength violated --> ColumnName: " + column.ColumnName + ", tableName: " + column.Table.TableName);
}
}
}
}
以防有人像我一样正在VB.NET中使用遗留项目的数据集来节省你们一分钟,我在@AFract答案上发布了一个VB.NET版本。希望它适合这里:
Catch ex As ConstraintException
Dim rowErrors = this.YourDataSet.YourDataTable.GetErrors()
System.Diagnostics.Debug.WriteLine("YourDataTable Errors:" & rowErrors.Length)
For i = 0 To rowErrors.Length - 1
For Each col As DataColumn In rowErrors(i).GetColumnsInError()
System.Diagnostics.Debug.WriteLine(col.ColumnName & ":" & rowErrors(i).GetColumnError(col))
Next
Next
End Try
简短回答:不,你可以用动态sql做一些不好的事情,但我不建议这样做。谢谢@Tristan,我现在改变了我的问题尝试从dbo中选择f.*f。水果作为f,如果不存在,从dbo中选择1。类别作为c,其中c.id=f.categoryID;为了找出哪些行违反了FK约束。我没有对此进行测试,但我会接受它,感谢遗留项目中的Life saver。非常感谢。如果使用Visual Studio调试并在异常时停止,则可以在即时窗口中键入:yourDataset.yourTable.GetErrors[0].RowError,您将看到第一个约束错误