常见问题解答

以下部分回答了在实现 LINQ 时可能会遇到的一些常见问题。

故障排除中解决了其他问题。

无法连接

无法连接到数据库。

确保连接字符串正确且 SQL Server 实例正在运行。 另请注意,LINQ to SQL 要求启用命名管道协议。 有关详细信息,请参阅 “按演练学习”。

数据库丢失更改

我更改了数据库中的数据,但重新运行应用程序时,更改不再存在。

请确保调用 SubmitChanges 以将结果保存到数据库。

数据库连接:打开多长时间?

数据库连接保持打开多长时间?

连接通常保持打开状态,直到使用查询结果。 如果希望花时间处理所有结果,并且不反对缓存结果,请应用于 ToList 查询。 在仅处理一次每个对象的常见方案中,流式处理模型在 LINQ to SQL 中 DataReader 都优于。

连接使用情况的确切详细信息取决于以下内容:

在不查询的情况下更新

是否可以在不先查询数据库的情况下更新表数据?

尽管 LINQ to SQL 没有基于设置的更新命令,但可以使用以下任一技术进行更新,而无需先进行查询:

  • 用于 ExecuteCommand 发送 SQL 代码。

  • 创建对象的新实例并初始化影响更新的所有当前值(字段)。 然后,使用Attach对象并将其修改要更改的字段附加到DataContext该对象。

意外查询结果

我的查询返回意外的结果。 如何检查发生了什么情况?

LINQ to SQL 提供了多种工具来检查生成的 SQL 代码。 最重要的一个是 Log。 有关详细信息,请参阅 调试支持

意外存储过程结果

我有一个存储过程,其返回值由“MAX()”计算。 将存储过程拖到 O/R 设计器图面时,返回值不正确。

LINQ to SQL 通过存储过程提供两种方法来返回数据库生成的值:

  • 通过命名输出结果。

  • 通过显式指定输出参数。

下面是错误输出的示例。 由于 LINQ to SQL 无法映射结果,因此它始终返回 0:

create procedure proc2

as

begin

select max(i) from t where name like 'hello'

end

下面是使用输出参数的正确输出示例:

create procedure proc2

@result int OUTPUT

as

select @result = MAX(i) from t where name like 'hello'

go

下面是通过命名输出结果正确输出的示例:

create procedure proc2

as

begin

select nax(i) AS MaxResult from t where name like 'hello'

end

有关详细信息,请参阅 使用存储过程自定义作

序列化错误

尝试序列化时,出现以下错误:“Type 'System.Data.Linq.ChangeTracker+StandardChangeTracker' ...未标记为可序列化。

LINQ to SQL 中的代码生成支持 DataContractSerializer 序列化。 它不支持 XmlSerializerBinaryFormatter。 有关详细信息,请参阅序列化

多个 DBML 文件

如果有多个 DBML 文件共享某些表,则会出现编译器错误。

将对象关系设计器中的 上下文命名空间实体命名空间 属性设置为每个 DBML 文件的不同值。 此方法消除了名称/命名空间冲突。

避免在插入或更新时显式设置 Database-Generated 值

我有一个数据库表,其中包含默认为 SQL“Getdate()”的“DateCreated”列。 当我尝试使用 LINQ to SQL 插入新记录时,该值将设置为“NULL”。 我希望它设置为数据库默认值。

LINQ to SQL 会自动处理标识(自动递增)和 rowguidcol(数据库生成的 GUID)和时间戳列的这种情况。 在其他情况下,应手动设置IsDbGeneratedtrue=和Always=OnUpdateAutoSync/OnInsert/属性。

多个 DataLoadOptions

是否可以指定其他加载选项而不覆盖第一个选项?

是的。 第一个未覆盖,如以下示例所示:

Dim dlo As New DataLoadOptions()
dlo.LoadWith(Of Order)(Function(o As Order) o.Customer)
dlo.LoadWith(Of Order)(Function(o As Order) o.OrderDetails)
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Order>(o => o.Customer);
dlo.LoadWith<Order>(o => o.OrderDetails);

使用 SQL Compact 3.5 时出错

将表拖出 SQL Server Compact 3.5 数据库时,我会收到错误。

对象关系设计器不支持 SQL Server Compact 3.5,尽管 LINQ to SQL 运行时支持。 在这种情况下,必须创建自己的实体类并添加相应的属性。

继承关系中的错误

我使用了对象关系设计器中的工具箱继承形状来连接两个实体,但我收到错误。

创建关系是不够的。 必须提供信息,例如鉴别器列、基类鉴别器值和派生类鉴别器值。

提供程序模型

公共提供程序模型是否可用?

没有公共提供程序模型可用。 目前,LINQ to SQL 仅支持 SQL Server 和 SQL Server Compact 3.5。

SQL-Injection 攻击

LINQ to SQL 如何抵御 SQL 注入攻击?

SQL 注入对于连接用户输入构成的传统 SQL 查询来说是一个重大风险。 LINQ to SQL 在查询中使用 SqlParameter 可避免此类注入。 用户输入将转换为参数值。 此方法可防止恶意命令从客户输入中使用。

更改 DBML 文件中的只读标志

从 DBML 文件创建对象模型时,如何消除某些属性中的 setter?

对于此高级方案,请执行以下步骤:

  1. 在 .dbml 文件中,通过将标志更改为 IsReadOnlyTrue 来修改属性。

  2. 添加分部类。 使用只读成员的参数创建构造函数。

  3. 查看默认值 UpdateCheckNever) 以确定该值是否为应用程序的正确值。

    谨慎

    如果在 Visual Studio 中使用对象关系设计器,可能会覆盖更改。

APTCA

System.Data.Linq 是否标记为供部分受信任的代码使用?

是的,System.Data.Linq.dll 程序集是用属性标记的 AllowPartiallyTrustedCallersAttribute .NET Framework 程序集之一。 如果没有此标记,.NET Framework 中的程序集仅供完全信任的代码使用。

LINQ to SQL 中允许部分受信任的调用方的主要方案是允许从 Web 应用程序访问 LINQ to SQL 程序集,其中 信任 配置为中等。

映射来自多个表的数据

实体中的数据来自多个表。 如何映射它?

可以在数据库中创建视图,并将实体映射到视图。 LINQ to SQL 为视图生成与表相同的 SQL。

注释

此方案中的视图的使用有限制。 当基础视图支持执行 Table<TEntity> 的作时,此方法最安全。 只有你知道哪些作是预期作。 例如,大多数应用程序都是只读的,另一个大小的数字仅通过使用存储过程对视图执行Create//UpdateDelete作。

连接池

是否有有助于 DataContext 池的构造?

请勿尝试重复使用 . 的 DataContext实例。 每个 DataContext 维护一个特定编辑/查询会话的状态(包括标识缓存)。 若要根据数据库的当前状态获取新实例,请使用新的 DataContext实例。

你仍然可以使用基础 ADO.NET 连接池。 有关详细信息,请参阅 SQL Server 连接池 (ADO.NET)

第二个 DataContext 未更新

我使用了 DataContext 的一个实例将值存储在数据库中。 但是,同一数据库中的第二个 DataContext 不会反映更新的值。 第二个 DataContext 实例似乎返回缓存的值。

此行为是设计造成的。 LINQ to SQL 继续返回第一个实例中看到的相同实例/值。 进行更新时,请使用乐观并发。 原始数据用于检查当前数据库状态,以断言它实际上保持不变。 如果已更改,则会发生冲突,应用程序必须解决它。 应用程序的一个选项是将原始状态重置为当前数据库状态,然后重试更新。 有关详细信息,请参阅 “如何:管理更改冲突”。

还可以设置为 ObjectTrackingEnabled false,这会关闭缓存和更改跟踪。 然后,可以在每次查询时检索最新值。

无法在只读模式下调用 SubmitChanges

当我尝试在只读模式下调用 SubmitChanges 时,我会收到错误。

只读模式关闭上下文跟踪更改的能力。