LINQ to SQL генерирует "ноль" вместо "не ноль" из функции сервера SQL "вернуть таблицу как"

Я работаю с SQL Server Express 2012 с расширенными службами и Visual Studio 2013 с обновлением 2. Я упростил пример до самого ядра. У меня есть следующая таблица в моей базе данных:

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 stackru 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;
    }
  }
}

Таблица Realty генерируется правильно в файле 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'

Я обнаружил, что SQL Server делает то же самое, если вы создаете представление на основе таблицы Realty. Поиск ответа не нашел ничего авторитетного, но привел к аналогичной проблеме на сайте администраторов баз данных. Это привело к такому обсуждению, которое заставило меня попробовать использовать ISNULL, С использованием ISNULL hack, как в следующем примере, дает правильное определение столбца в файле DBML, как только я удалил предыдущую функцию из файла DBML и повторно добавил ее.

Требуется для принудительного вычисления вычисляемого столбца NotNullable:

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
Другие вопросы по тегам