Serexx
Serexx

Reputation: 1250

Asp.net Dynamic Data 4 One-to-One ForeignKey.ascx Returning Primary Key

I have a Dynamic Data 4 site using LinqToSql (.dbml) for 2 tables with a one-to-one relationship. One table (child) does not always have a row corresponding to the primary table.

Whenever that is the case (no child table row) instead of an empty row cell the DD ForeignKey.ascx Field template is displaying a link to:

Childtable/Detail.aspx?ChildPkField=PRIMARYTABLEGUID

I can't find any combination of SQL F-key setups and/or .dbml column property settings that prevent this. The only solution so far is a Custom ForeignKey.ascx template with

 protected string GetDisplayString()
    {
        object value = FieldValue;
        if (value == null)
        {
            //replace this
            //return FormatFieldValue(ForeignKeyColumn.GetForeignKeyString(Row));
            //with this
            return "";
        }
        else
        {
            return FormatFieldValue(ForeignKeyColumn.ParentTable.GetDisplayString(value));
        }
    }

Obviously not an optimal solution. To simplify I have removed all Custom Metadata for both tables and all other relationships the tables were involved in. No change.

I am sure it i something simple but I have looked at it for too long now - any help appreciated!

Here are the current Create Table Scripts from Sql Manager:

CREATE TABLE [dbo].[UserProfile](
[UserId] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
[ProfileUserName] [nvarchar](50) NOT NULL,
      CONSTRAINT [PK_Profile] 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] TEXTIMAGE_ON [PRIMARY]
 GO
 ALTER TABLE [dbo].[UserProfile] ADD  CONSTRAINT [DF_Profile_UserID]  DEFAULT (newid()) FOR [UserId]
GO

and

CREATE TABLE [dbo].[SubscribedUser](
[subUserId] [uniqueidentifier] NOT NULL,
[subExpireDate] [date] NULL,
     CONSTRAINT [PK_SubscribedUsers] PRIMARY KEY CLUSTERED ([subUserId] 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].[SubscribedUser]  WITH CHECK ADD  CONSTRAINT [FK_SubscribedUser_UserProfile] FOREIGN KEY([subUserId]) REFERENCES [dbo].[UserProfile] ([UserId])
GO
ALTER TABLE [dbo].[SubscribedUser] CHECK CONSTRAINT [FK_SubscribedUser_UserProfile]
GO

Upvotes: 0

Views: 737

Answers (2)

Interarticle
Interarticle

Reputation: 385

In fact, the first method you used is perhaps the most optimal solution as the query has already been made on the server-side to determine whether the column data matches the foreign key relationship. No more querying is needed, just test FieldValue == null. Besides, the template controls are there to be edited, which is why they're not compiled to assemblies:

protected string GetDisplayString()
{
    object value = FieldValue;
    if (value == null)
    {
        //replace this
        //return FormatFieldValue(ForeignKeyColumn.GetForeignKeyString(Row));
        //with this
        return "";
    }
    else
    {
        return FormatFieldValue(ForeignKeyColumn.ParentTable.GetDisplayString(value));
    }
}

However, if you intend to preserved the value of the source field, use this method instead:

protected string GetNavigateUrl()
{
    //replace this
    //if (!AllowNavigation)
    //with this
    if (!AllowNavigation || FieldValue == null)
    {
        return null;
    }
    if (String.IsNullOrEmpty(NavigateUrl))
    {
        return ForeignKeyPath;
    }
    else
    {
        return BuildForeignKeyPath(NavigateUrl);
    }
}

Under certain conditions (including the default css styles), it will generate a hyperlink-looking field that cannot be clicked. You can use jQuery to filter and remove those false hyperlinks by setting their outerHTML as their innerHTML (client-side scripting). Of course, there are more elegant methods like adding a <asp:label> to the ForeignKey.ascx and switching to that control when needed.

Note: this method works when using ADO.NET Entity Data Model. I didn't try it on LinqToSqlClasses.

Upvotes: 2

F.Filippi
F.Filippi

Reputation: 93

Have you tried to remove both tables from the linq2sql class and then readd them again? Maybe recreating the relation again in the schema even before that?

F.

Upvotes: 0

Related Questions