实体框架包括表空

时间:2016-09-26 16:58:07

标签: entity-framework

我首先使用db,并且使用以下命令始终返回null的特定关联:

    var results = _ABPRepository.Query(x => x.ABPArrangementId == arrangementId)
                    .Include(x => x.tb_ARRArrangement)
                    .Include(x => x.tb_ARRArrangement.Supplier)
                    .Include(x => x.tb_ARRArrangement.Supplier.tb_SCNSicCodesNew)
                    .Include(x => x.tb_BBRBatteryBackBrands)
                    .Include(x => x.tb_ARRArrangement.Supplier.Country)
                    .Include(x => x.tb_ARRArrangement.Supplier.InvoiceCountry)
                    .Include(x => x.Country)
                    .Select().FirstOrDefault();

以下内容始终为空:

x.tb_ARRArrangement.Supplier.tb_SCNSicCodesNew

我已经验证了SQL是正确的(简要说明如下):

SELECT 
    /* ... */
    [Project1].[SCN_SIC_Code] AS [SCN_SIC_Code], 
    [Project1].[SCN_SIC_Description] AS [SCN_SIC_Description]
    /* ... */
    FROM ( SELECT 
        /* ... */
        [Extent4].[SCN_SIC_Code] AS [SCN_SIC_Code], 
        [Extent4].[SCN_SIC_Description] AS [SCN_SIC_Description],
        /* ... */
        CASE WHEN ([Extent8].[BBRIDNumber] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
        FROM        [dbo].[tb_ABPArrangementBatteryBackProducer] AS [Extent1]
        INNER JOIN [dbo].[tb_ARRArrangement] AS [Extent2] ON [Extent1].[ABPArrangementId] = [Extent2].[ARRIDNumber]
        LEFT OUTER JOIN [dbo].[tb_SUPSupplier] AS [Extent3] ON [Extent2].[ARRSupplierId] = [Extent3].[SUPKey]
        LEFT OUTER JOIN (SELECT 
                                [tb_SCNSicCodesNew].[SCN_SIC_Code] AS [SCN_SIC_Code], 
                                [tb_SCNSicCodesNew].[SCN_SIC_Description] AS [SCN_SIC_Description]
                         FROM [dbo].[tb_SCNSicCodesNew] AS [tb_SCNSicCodesNew]) AS [Extent4] ON [Extent3].[SUPEaHwrSicCode2007] = [Extent4].[SCN_SIC_Code]
        LEFT OUTER JOIN [dbo].[tb_COUCountry] AS [Extent5] ON [Extent3].[SUPCountry] = [Extent5].[COUIDNumber]
        LEFT OUTER JOIN [dbo].[tb_COUCountry] AS [Extent6] ON [Extent3].[SUPInvoiceCountry] = [Extent6].[COUIDNumber]
        INNER JOIN [dbo].[tb_COUCountry] AS [Extent7] ON [Extent1].[ABPCorrespondanceCountry] = [Extent7].[COUIDNumber]
        LEFT OUTER JOIN [dbo].[tb_BBRBatteryBackBrands] AS [Extent8] ON [Extent1].[ABPArrangementId] = [Extent8].[BBRABPIDNumber]
        WHERE [Extent1].[ABPArrangementId] = 123456
    )  AS [Project1]

返回的记录集包含我期望的数据,但无法映射到 results.tb_ARRArrangement.Supplier.tb_SCNSicCodesNew财产。

所有其他包括按预期工作。

我试过了:

  • 阅读包含哪些内容可能不起作用(分组等)但是它们 似乎不适用于我的场景,因为包含不被忽略, 更多的是映射似乎失败了。

  • 从EDMX中删除关联和表格并重新添加

  • 重命名并重新制作关联和导航属性

  • 清洁和重建

表格之间的数据库中没有外键,但是其他一些也没有,我也没有问题。

有关要检查的事项的任何指示?

1 个答案:

答案 0 :(得分:0)

这是Entity Framework中的一个问题,它将固定长度的字符串连接到可变长度,如下所述:https://romiller.com/2014/10/20/ef6-1workaround-trailing-blanks-issue-in-string-joins/

  

问题是SQL Server在比较时忽略了尾随空格   字符串,但.NET字符串函数(EF使用)不。在SQL上   服务器“ABCD”和“ABCD”被认为是相同的,但在.NET(和   EF)他们不是。

这导致选择了正确的数据但未映射。上面链接中的代码通过添加拦截器来修剪字符串来解决问题:

using System.Data.Entity.Core.Common.CommandTrees;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure.Interception;
using System.Linq;

namespace DataRepository
{
    public class StringTrimmerInterceptor : IDbCommandTreeInterceptor
    {
        public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
        {
            if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
            {
                var queryCommand = interceptionContext.Result as DbQueryCommandTree;
                if (queryCommand != null)
                {
                    var newQuery = queryCommand.Query.Accept(new StringTrimmerQueryVisitor());
                    interceptionContext.Result = new DbQueryCommandTree(
                        queryCommand.MetadataWorkspace,
                        queryCommand.DataSpace,
                        newQuery);
                }
            }
        }

        private class StringTrimmerQueryVisitor : DefaultExpressionVisitor
        {
            private static readonly string[] _typesToTrim = { "nvarchar", "varchar", "char", "nchar" };

        public override DbExpression Visit(DbNewInstanceExpression expression)
        {
            var arguments = expression.Arguments.Select(a =>
            {
                var propertyArg = a as DbPropertyExpression;
                if (propertyArg != null && _typesToTrim.Contains(propertyArg.Property.TypeUsage.EdmType.Name))
                    {
                    return EdmFunctions.Trim(a);
                }

                return a;
            });

            return DbExpressionBuilder.New(expression.ResultType, arguments);
        }
    }
}
}

然后通过将下面的内容放在与上下文相同的项目中来初始化:

using System.Data.Entity;

namespace FixedLengthDemo
{
    public class MyConfiguration : DbConfiguration
    {
        public MyConfiguration()
        {
            AddInterceptor(new StringTrimmerInterceptor());
        }
    }
}