【问题标题】:LINQ to SQL generate "null" instead of "not null" from sql server function "return table as"LINQ to SQL 从 sql server 函数“return table as”生成“null”而不是“not null”
【发布时间】:2014-07-25 15:09:01
【问题描述】:

我正在使用具有高级服务和 Visual Studio 2013 更新 2 的 SQL Server Express 2012。我已将示例简化为核心。我的数据库中有下表:

CREATE TABLE [dbo].[Realty]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
...
...
[RankingBonus] [int] NOT NULL,
[Ranking]  AS ([Id]+[RankingBonus]) PERSISTED NOT NULL,
...
)

在此表上具有全文表功能:

CREATE FUNCTION [dbo].[GetFilteredRealtyFulltext]
(@fulltextcriteria nvarchar(4000))
RETURNS TABLE
AS
RETURN (SELECT 
realty.Id AS realtyId,
...
realty.Ranking, --THIS IS IMPORTANT FOR THE QUIESTION!
...,
( COALESCE(ftR.Rank,0) + COALESCE(ftObec.Rank,0) + COALESCE(ftOkres.Rank,0) + COALESCE(ftpobvod.Rank,0)) AS FtRank

FROM realty
--these joins and where conditions are not important for this stackoverflow question
--this only shows why I use table function with return table
--it is because this is the only way I found how to generate LINQ to SQL with fulltext as IQueryable<T>
JOIN Category ON realty.CategoryId = Category.Id
LEFT JOIN ruian_cobce ON realty.cobceId = ruian_cobce.cobce_kod
LEFT JOIN ruian_obec ON realty.obecId = ruian_obec.obec_kod
LEFT JOIN okres ON realty.okresId = okres.okres_kod
LEFT JOIN ExternFile ON realty.Id = ExternFile.ForeignId AND ExternFile.IsMain = 1 AND ExternFile.ForeignTable = 5
INNER JOIN Person ON realty.OwnerId = Person.Id
Left JOIN CONTAINSTABLE(Realty, *, @fulltextcriteria) ftR ON realty.Id = ftR.[Key] 
Left JOIN CONTAINSTABLE(ruian_obec, *, @fulltextcriteria) ftObec ON realty.obecId = ftObec.[Key] 
Left JOIN CONTAINSTABLE(Okres, *, @fulltextcriteria) ftOkres ON realty.okresId = ftOkres.[Key]
Left JOIN CONTAINSTABLE(pobvod, *, @fulltextcriteria) ftpobvod ON realty.pobvodId = ftpobvod.[Key]
WHERE Person.ConfirmStatus = 1
AND ( COALESCE(ftR.Rank,0) + COALESCE(ftObec.Rank,0) + COALESCE(ftOkres.Rank,0) + COALESCE(ftpobvod.Rank,0))  > 0
)
GO

当我将函数 GetFilteredRealtyFulltext 放入 DBML 时,设计器将列 Ranking 生成为 Nullable int

[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Ranking", DbType="Int")]
public System.Nullable<int> Ranking
{
  get
  {
    return this._Ranking;
  }
  set
  {
    if ((this._Ranking != value))
    {
       this._Ranking = value;
    }
  }
}

我希望它应该只生成 整数

[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Ranking", DbType="Int NOT NULL"")]
public int Ranking
{
  get
  {
    return this._Ranking;
  }
  set
  {
    if ((this._Ranking != value))
    {
       this._Ranking = value;
    }
  }
}

在DBML文件中正确生成了表格Realty,Ranking只是整数,但是表格函数生成错误。它有什么问题?

更新:

Linked question 直奔问题的核心。

【问题讨论】:

    标签: sql-server linq-to-sql nullable dbml


    【解决方案1】:

    问题是 SQL Server 认为 Ranking 来自 GetFilteredRealtyFulltext 函数的列可以为空,即使基础表列创建为 NOT NULL。您可以通过对您的数据库运行以下查询来查看这一点:

    select 
    o.name ObjectName,
    c.name ColumnName,
    c.is_nullable ColumnIsNullable
    from 
    sys.all_objects o 
    inner join 
    sys.all_columns c 
    on 
    o.object_id = c.object_id 
    where 
    o.[name] = 'GetFilteredRealtyFulltext'
    

    我发现如果您基于 Realty 表创建视图,SQL Server 会做同样的事情。谷歌搜索没有找到任何权威的答案,但确实导致了数据库管理员站点上的similar problem。这导致了this SO 讨论,这让我尝试使用ISNULL。在我从 DBML 文件中删除前一个函数并重新添加后,使用下面示例中的 ISNULL hack 可以在 DBML 文件中提供正确的列定义。

    需要force computed columnNotNullable:

    CREATE TABLE [dbo].[Realty]
    (
    [Id] [int] IDENTITY(1,1) NOT NULL,
    ...
    ...
    [RankingBonus] [int] NOT NULL,
    [Ranking]  AS ISNULL([Id]+[RankingBonus], 0) PERSISTED NOT NULL,
    ...
    )
    

    然后强制函数也不能为空:

    CREATE FUNCTION [dbo].[GetFilteredRealtyFulltext]
    (@fulltextcriteria nvarchar(4000))
    RETURNS TABLE
    AS
    RETURN (SELECT 
    realty.Id AS realtyId,
    realty.RankingBonus,
    ISNULL(realty.Ranking, 0) as Ranking  --ISNULL hack
    FROM realty
    )
    GO
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多