LINQ to SQL generate “null” instead of “not null” from sql server function “return table as”
我正在使用SQL Server Express 2012高级服务和Visual Studio 2013更新2。我已经将这个例子简化到核心。我的数据库中有下表:
1 2 3 4 5 6 7 8 9 | CREATE TABLE [dbo].[Realty] ( [Id] [int] IDENTITY(1,1) NOT NULL, ... ... [RankingBonus] [int] NOT NULL, [Ranking] AS ([Id]+[RankingBonus]) PERSISTED NOT NULL, ... ) |
在此表上具有全文表功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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中时,设计器生成列排名为nullable int。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [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; } } } |
我希望它只生成整数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [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文件中生成正确,排名仅为整数,但表函数生成错误。怎么了?
更新:
将问题与问题的核心联系起来。
问题是,SQL Server认为来自
1 2 3 4 5 6 7 8 9 10 11 12 | 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也会做同样的事情。谷歌搜索并没有找到任何权威性的答案,但在数据库管理员网站上确实导致了类似的问题。这导致了这样的讨论,这让我尝试使用
强制计算列NotNullable需要Is:
1 2 3 4 5 6 7 8 9 | CREATE TABLE [dbo].[Realty] ( [Id] [int] IDENTITY(1,1) NOT NULL, ... ... [RankingBonus] [int] NOT NULL, [Ranking] AS ISNULL([Id]+[RankingBonus], 0) PERSISTED NOT NULL, ... ) |
然后强制函数也不能为空:
1 2 3 4 5 6 7 8 9 10 11 | 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 |