0

複合主キーを持つテーブルに DbSyncForeignKeyConstraint を作成しようとしていますが、エラーが発生し続けます。私がやっていることを示すサンプルコードを次に示します。

例の表:

USE [TempTest]
GO

CREATE TABLE [dbo].[Users](
        [UserId] [uniqueidentifier] NOT NULL,
    CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
    (
        [UserId] ASC
    )
    WITH 
    (
        PAD_INDEX  = OFF, 
        STATISTICS_NORECOMPUTE  = OFF, 
        IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS  = ON, 
        ALLOW_PAGE_LOCKS  = ON
    ) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[UsersRoles](
    [UserId] [uniqueidentifier] NOT NULL,
    [RoleId] [uniqueidentifier] NOT NULL,
    CONSTRAINT [PK_UsersRoles] PRIMARY KEY CLUSTERED 
    (
        [UserId] ASC,
        [RoleId] 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

ここに私のC#コードがあります:

DbSyncTableDescription tableDesc = SqlSyncDescriptionBuilder.GetDescriptionForTable("UsersRoles", (SqlConnection)this.dbProvider.Connection);
Collection<string> parentkeys = new Collection<string>();
parentkeys.Add("UserId"); 
Collection<string> childkeys = new Collection<string>();
childkeys.Add("RoleId");
childkeys.Add("UserId");
tableDesc.Constraints.Add(new DbSyncForeignKeyConstraint("FK_UsersRoles_Users", "Users", "UsersRoles", parentkeys, childkeys));

上記のコードでは、次のエラーが発生します。

参照関係の参照列の定義 (列数やデータ型など) は、参照先の列と一致する必要があります。

の行をコメント アウトするとchildkeys.Add("RoleId")、次のエラーが表示されます。「参照されるテーブルには、主キーまたは候補キーが必要です。」

そのため、これをどのように行うべきかについては少し不明です。この例では、制約は実際には UserId 列に関するものにすぎません。しかし、UsersRoles テーブルには複合主キーがあるので、それを制約に含めるべきでしょうか? 制約定義で「RoleId」を省略すると、エラーが発生します...含めると、別のエラーが発生します。

私がどのように進めるべきかについて誰か提案がありますか? (PS:通常の非複合主キーを持つテーブル間に他の外部キーを作成するコードがあり、そのコードはエラーなしで機能します)。

追加情報で編集: OK. DBSyncForeignKeyConstraint の作成には問題がないようです。問題は GetDescriptionForTable 機能にあるようです。UserId を主キーとして取得していないようです。私のプロジェクトでは、実際に aspnet_Membership スキーマを使用するデータベースに対して作業しています。したがって、aspnet_Users テーブルのスクリプトを作成すると、次のようになります。 ' CREATE TABLE [dbo].[aspnet_Users](
[ApplicationId] [uniqueidentifier] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[UserName] nvarchar NOT NULL,
[LoweredUserName] nvarchar NOT NULL,
[MobileAlias] nvarchar NULL,
[IsAnonymous] [bit] NOT NULL,
[LastActivityDate] [datetime] NOT NULL, PRIMARY KEY NONCLUSTERED ( [UserId] 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].[aspnet_Users] WITH CHECK ADD FOREIGN KEY([ApplicationId]) REFERENCES [dbo].[aspnet_Applications] ([ApplicationId]) GO
ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT (newid()) FOR [UserId]
GO
ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT (NULL) FOR [MobileAlias]
GO
ALTER TABLE [dbo] [aspnet_Users] ADD DEFAULT ((0)) FOR [IsAnonymous] GO'

しかし、「GetScopeDescription」を呼び出した結果を調べると、列「ApplicationId」と「LoweredUserName」が PKColumns としてリストされ、UserId が NonPkColumns にリストされていることがわかります。何が原因なのかわかりません。しかし、少なくとも、列「UserId」が主キーに含まれていないというエラーが表示される理由を理解しています。データベースにはありますが、GetScopDescription の結果にはありません。ですから、少なくともどの方向から検索を開始すればよいかはわかっています。

4

3 に答える 3

0

これは、テーブル構造を取得するためにSync Fxによって内部的に使用されるDataReaderのGetSchemaTableによるもののように見えます(http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/c1c113e2-32dc-4826-を参照)。 b6e0-17dff29c1baf

回避策として、PKを自分で設定するだけです。

例えば、

downloadOnlyScopeDesc.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable("aspnet_Users", (System.Data.SqlClient.SqlConnection)provider.Connection));

//untag wrong PK information
foreach(var pkColumn in downloadOnlyScopeDesc.Tables["aspnet_Users"].PkColumns)
{
    downloadOnlyScopeDesc.Tables["aspnet_Users"].Columns[pkColumn.QuotedName].IsPrimaryKey = false;
}

//tag the correct PK
downloadOnlyScopeDesc.Tables["aspnet_Users"].Columns["UserId"].IsPrimaryKey = true;
于 2012-09-26T01:58:39.830 に答える
0

OK、これはスコープ プロビジョニング機能のかなり深刻な問題のようです。プロビジョニングされたソース データベースに移動し、scope_config テーブルの config_data 列のデータを確認すると、xml で aspnet_Users テーブルが間違った方法で記述されていることがわかります。

  <Adapter Name="[aspnet_Users]" GlobalName="[aspnet_Users]" TrackingTable="[aspnet_Users_tracking]" SelChngProc="[aspnet_Users_selectchanges]" SelRowProc="[aspnet_Users_selectrow]" InsProc="[aspnet_Users_insert]" UpdProc="[aspnet_Users_update]" DelProc="[aspnet_Users_delete]" InsMetaProc="[aspnet_Users_insertmetadata]" UpdMetaProc="[aspnet_Users_updatemetadata]" DelMetaProc="[aspnet_Users_deletemetadata]" BulkTableType="[aspnet_Users_BulkType]" BulkInsProc="[aspnet_Users_bulkinsert]" BulkUpdProc="[aspnet_Users_bulkupdate]" BulkDelProc="[aspnet_Users_bulkdelete]" InsTrig="[aspnet_Users_insert_trigger]" UpdTrig="[aspnet_Users_update_trigger]" DelTrig="[aspnet_Users_delete_trigger]">
<Col name="ApplicationId" type="uniqueidentifier" param="@P_1" pk="true" />
<Col name="UserId" type="uniqueidentifier" param="@P_2" />
<Col name="UserName" type="nvarchar" size="256" param="@P_3" />
<Col name="LoweredUserName" type="nvarchar" size="256" param="@P_4" pk="true" />
<Col name="MobileAlias" type="nvarchar" size="16" null="true" param="@P_5" />
<Col name="IsAnonymous" type="bit" param="@P_6" />
<Col name="LastActivityDate" type="datetime" param="@P_7" />

ApplicationId 列と LoweredUserName 列が pks としてマークされているのに、マークされていないことがわかります。また、UserId 列は、本来あるべきときに pk としてマークされていません。この誤ったデータにより、aspnet_Users テーブル用に作成された追跡テーブルが正しく構造化されないため、scope_config テーブルの xml を修正するだけでは問題を解決するには不十分です。そのため、修正に多少の作業が必要なかなり大きな問題に遭遇したようです。サーバー構成を実行するときにパラメーターを設定していないため、このエラーを作成するために何もしていないと思います。

私はこの問題の説明を他のどこにも見つけることができませんでした。これは本当に奇妙なことですが、探し続けます。

うーん!

エクスプローラーからの画像を SQL Server Management Studio に含めます。

JuneT さん、ご協力いただきありがとうございます。

ここに画像の説明を入力

于 2012-09-23T18:20:02.987 に答える
0

コードのプロビジョニングがどのように見えるかはわかりませんが、これは完全に正常に機能します

        var sqlConn = new SqlConnection(@"Data Source=(local)\SQLExpress; Initial Catalog=Test; Integrated Security=True");
        var sqlConn2 = new SqlConnection(@"Data Source=(local)\SQLExpress; Initial Catalog=Test2; Integrated Security=True");

        var parent = SqlSyncDescriptionBuilder.GetDescriptionForTable("Users", sqlConn);
        var child = SqlSyncDescriptionBuilder.GetDescriptionForTable("UsersRoles", sqlConn);

        var parentPKColumns = new Collection<string> {"UserId"};
        var childFKColumns = new Collection<string> {"UserId"};

        child.Constraints.Add(new DbSyncForeignKeyConstraint("FK_UsersRoles_Users", "Users", "UsersRoles", parentPKColumns, childFKColumns));

        var fKTestScope= new DbSyncScopeDescription("FKTestScope");

        fKTestScope.Tables.Add(parent);
        fKTestScope.Tables.Add(child);

        var scopeProvisioning = new SqlSyncScopeProvisioning(sqlConn2, fKTestScope);

        scopeProvisioning.Apply();
于 2012-09-22T03:00:41.883 に答える