未生成 SQLMetal DataContext 关联
我正在为数据库生成 LINQ-to-SQL DataContext 和实体类。该数据库有多个表,其中两个是 - [AccountMaster] 和 [AccountCodes]。它们之间定义了外键关系,[AccountMaster].AccountNumber 是从[AccountCodes] 引用的。
在 VS2008 中添加 LINQ-to-SQL 文件并将这些表拖到 DBML 设计视图上,会在 AccountMaster 类中生成一个 AccountNotes 集合。同时,使用SQLMetal生成DataContext不会生成任何EntitySet集合。
设计器输出:
[Table(Name="dbo.A01_AccountMaster")]
public partial class A01_AccountMaster //...
{
//...
private long _AccountNumber;
private EntitySet<A01aAccountNote> _A01aAccountNotes;
//...
}
SQLMetal 输出:
[Table(Name="dbo.A01_AccountMaster")]
[DataContract()]
public partial class A01_AccountMaster //...
{
//...
private long _AccountNumber;
//...
}
的指南
我正在遵循http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx< /a>
我尝试首先使用 SQLMetal 生成 DBML 文件,然后从生成的 DBML 生成 DataContext.cs 文件:
sqlmetal.exe /server:srv /database:db /user:usr /password:pwd /sprocs /namespace:AccountContext /context:AccountContext /dbml:AccountContext.dbml /language:csharp /serialization:unidirectional
sqlmetal.exe /sprocs /namespace:AccountContext /context:AccountContext /code:AccountContext.cs /language:csharp /serialization:unidirectional AccountContext.dbml
这不会生成关联。事实上,从 SQLMetal 与设计器视图检查 DBML 文件:
设计视图 DBML:
<Type Name="A01_AccountMaster">
<!-- ... -->
<Column Name="AccountNumber" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
<Association Name="A01_AccountMaster_A01aAccountNote" Member="A01aAccountNotes" ThisKey="AccountNumber" OtherKey="AccountNumber" Type="A01aAccountNote" />
<!-- ... -->
</Type>
SQLMetal DBML:
<Type Name="A01_AccountMaster">
<!-- ... -->
<Column Name="AccountNumber" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
<!-- ... -->
</Type>
因此在 DBML 步骤中已经缺少关联。
由于数据库包含大量表/存储过程,因此使用设计器重新生成 DataContext 类是不切实际的。如何让 SQLMetal 正确生成关联?
编辑:
在整个数据库上运行 SQLMetal,我意识到某些实体关联正在正确生成。 AccountNotes 上的外键定义为:
ALTER TABLE [dbo].[A01aAccountNotes] WITH CHECK ADD CONSTRAINT [FK_A01aAccountNotes_A01_AccountMaster] FOREIGN KEY([AccountNumber])
REFERENCES [dbo].[A01_AccountMaster] ([AccountNumber])
GO
ALTER TABLE [dbo].[A01aAccountNotes] CHECK CONSTRAINT [FK_A01aAccountNotes_A01_AccountMaster]
GO
EDIT2:
我注意到正确创建的关联是那些具有 ON DELETE CASCADE/UPDATE 规则的关联。那么生成没有在数据库级别严格定义此规则的关联是没有意义的吗?
I am generating the LINQ-to-SQL DataContext and entity classes for a database. The database has several tables, two of which are - [AccountMaster] and [AccountCodes]. There is a foreign key relationship defined between them, with [AccountMaster].AccountNumber being referenced from [AccountCodes].
Adding a LINQ-to-SQL file in VS2008 and dragging these tables onto the DBML design view appropriately generates a collection of AccountNotes within the AccountMaster class. Meanwhile, using SQLMetal to generate the DataContext does not produce any EntitySet collections.
Designer output:
[Table(Name="dbo.A01_AccountMaster")]
public partial class A01_AccountMaster //...
{
//...
private long _AccountNumber;
private EntitySet<A01aAccountNote> _A01aAccountNotes;
//...
}
SQLMetal output:
[Table(Name="dbo.A01_AccountMaster")]
[DataContract()]
public partial class A01_AccountMaster //...
{
//...
private long _AccountNumber;
//...
}
I am following the guide at
http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx
I have tried to first generate the DBML file using SQLMetal, and then generate the DataContext.cs file from the resulting DBML:
sqlmetal.exe /server:srv /database:db /user:usr /password:pwd /sprocs /namespace:AccountContext /context:AccountContext /dbml:AccountContext.dbml /language:csharp /serialization:unidirectional
sqlmetal.exe /sprocs /namespace:AccountContext /context:AccountContext /code:AccountContext.cs /language:csharp /serialization:unidirectional AccountContext.dbml
This does not generate the associations. In fact, inspecting the DBML files from SQLMetal vs. the designer view:
Design View DBML:
<Type Name="A01_AccountMaster">
<!-- ... -->
<Column Name="AccountNumber" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
<Association Name="A01_AccountMaster_A01aAccountNote" Member="A01aAccountNotes" ThisKey="AccountNumber" OtherKey="AccountNumber" Type="A01aAccountNote" />
<!-- ... -->
</Type>
SQLMetal DBML:
<Type Name="A01_AccountMaster">
<!-- ... -->
<Column Name="AccountNumber" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
<!-- ... -->
</Type>
So the association is missing already at the DBML step.
Since the database contains tons of tables/sprocs, it is not practical to use the designer to regenerate the DataContext classes. How do I make SQLMetal generate associations correctly?
EDIT:
Running SQLMetal on the entire database, I realized that SOME entity associations are being generated correctly. The foreign key on AccountNotes is defined as:
ALTER TABLE [dbo].[A01aAccountNotes] WITH CHECK ADD CONSTRAINT [FK_A01aAccountNotes_A01_AccountMaster] FOREIGN KEY([AccountNumber])
REFERENCES [dbo].[A01_AccountMaster] ([AccountNumber])
GO
ALTER TABLE [dbo].[A01aAccountNotes] CHECK CONSTRAINT [FK_A01aAccountNotes_A01_AccountMaster]
GO
EDIT2:
I've noticed that the associations correctly created are those which have an ON DELETE CASCADE/UPDATE rule. Is it then nonsensical to generate associations which do not have this rule strictly defined at the database level?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我们遇到了类似的问题,其中一个表有一个冗余索引,该索引被定义为表主键列上的唯一非聚集索引,而该列已经是聚集索引。当我们尝试删除非聚集索引时,SQL Server 拒绝了,因为有外键依赖于它。我们必须删除所有外键,删除索引,重新创建外键(现在取决于实际的 PK),然后 SQL Metal 就很高兴了。
We had a similar issue where a table had a redundant index that was defined as a unique, non-clustered index on the column that is the tables primary key that is already the clustered index. When we tried to delete the non-clustered index, SQL Server resisted because there were foreign keys depending on it. We had to drop all the foreign keys, delete the index, recreate the foreign keys (now depending on the actual PK) and then SQL Metal was happy.
听起来要么是 SQLMetal 中存在错误,要么是数据库中存在一些不一致。
你会得到不同的提取结果,因为它是两个不同的代码库(不要问)。
您可以做的一件事是打开 SQL 跟踪来观察 SqlMetal 发送到数据库以检索列表的 TSQL DDL 命令。它们是具有各种联接的 INFORMATION_SCHEMA 查询的组合。
听起来好像查看关联所需的连接的一部分失败了。如果将其发送到 SQL Server 的查询复制到 SQL Management Studio 窗口中并运行它们,您可能还会发现关联丢失。
一旦您确认了这种情况,您可以尝试将某些连接转换为 LEFT 连接,以查看哪一部分失败(或删除一些 WHERE 标准)。在某些时候,查询将返回关联。
然后,您可以调整架构,使其正常工作(SQLMetal 的源不可用:( )
Sounds like either there is a bug in SQLMetal or some inconsistency in the database.
You'll get different results extracting as it's two different codebases (don't ask).
One thing you could do is turn on SQL tracing to observe the TSQL DDL commands SqlMetal sends to the database to retrieve the list. They are a combination of INFORMATION_SCHEMA queries with various joins.
It sounds like one part of the join required for seeing the associations is misfiring. If you copy the queries it sends to SQL Server into a SQL Management Studio window and run them you'll probably also see the associations missing.
Once you've confirmed that's the case you could try turning some of the joins into LEFT joins to see which part is failing (or remove some WHERE criteria). At some point the query will return the associations.
You may then be able to tweak the schema so it works (the source for SQLMetal isn't available :( )