繁体   English   中英

当包含涉及2个联接的同一个表的子集合导航属性时,列名无效

[英]Invalid column name when including child collection navigation property involving 2 joins to the same table

我已经编写了一个存储库GetList函数,该函数对大多数导航属性都适用。 但是,当我尝试包含基于实体集合的特定导航属性时,它会失败。

以下域类涉及多对多关系

[Table("Template")]
public class Template : LoggedEntity
{
    public string Description { get; set; }

    public virtual ICollection<TemplateTask> Tasks { get; set; }
}

[Table("TemplateTask")]
public class TemplateTask : LoggedEntity
{
    [Column("TemplateId")]
    public int TemplateId { get; set; }

    [ForeignKey("TemplateId")]
    public virtual Template Template { get; set; }

    public virtual ICollection<TemplateTaskDependancy>  Dependancies { get; set; }  

    public virtual ICollection<TemplateTaskDependancy> NeededTasks { get; set; }
}

[Table("TemplateTaskDependancy")]
public class TemplateTaskDependancy : LoggedEntity
{
    [Column]
    public int NeededTaskId { get; set; }

    [Column]
    public int TaskId { get; set; }

    [Required]
    [ForeignKey("TaskId")]
    public virtual TemplateTask Task { get; set; }

    [Required]
    [ForeignKey("NeededTaskId")]
    public virtual TemplateTask NeededTask { get; set; }
}

[Table("LoggedEntity")]
public class LoggedEntity
{
    public int Id { get; set; }
}

以下失败

public IList<TemplateTask> GetTaskData()
{
    using (var uow = new UnitOfWork<TemplateContext>())
    using (var repository = new TemplateTaskRepository(uow))
    {
        int templateId = 1;
        return repository.GetList(p => p.Template.Id == templateId,
                                  a => a.Template, 
                                  c => c.Dependancies);  // runtime error occurs if c.Dependancies is included
    }
}

在下面的作品

public IList<TemplateTask> GetTaskData()
{
    using (var uow = new UnitOfWork<TemplateContext>())
    using (var repository = new TemplateTaskRepository(uow))
    {
        int templateId = 1;
        return repository.GetList(p => p.Template.Id == templateId,
        a => a.Template);   
    }
}

我的存储库类是:

 // based on Julie Lerman's repository pattern
 public class TemplateTaskRepository : LoggedEntityRepositoryBase<TemplateTask>, ITemplateTaskRepository
 {
    public TemplateTaskRepository(IUnitOfWork uow) : base(uow)
    {
    }
}

public interface ITemplateTaskRepository : IEntityRepository<TemplateTask>
{
}

public class LoggedEntityRepositoryBase<T> : IEntityRepository<T> where T : LoggedEntity
{
    private readonly IContext context;
    private readonly bool hasUnitOfWork;

    public LoggedEntityRepositoryBase(IUnitOfWork uow)
    {
        hasUnitOfWork = true;
        context = uow.Context;
    }

    public LoggedEntityRepositoryBase(IContext pContext)
    {
        context = pContext;
    }

    public IContext IContext
    {
        get
        {
            return context;
        }
    }
    public virtual IList<T> GetList(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties)
    {
        List<T> list;
        IQueryable<T> dbQuery = ((DbContext)context).Set<T>();

        //Apply eager loading
        foreach (var navigationProperty in navigationProperties)
        {
            dbQuery = dbQuery.Include(navigationProperty);
        }

        list = dbQuery.AsNoTracking().Where(where).ToList(); // error occurs here

        return list;
    }
 // etc
}

public interface IEntityRepository<T> : IDisposable where T : class
{
    IList<T> GetList(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
    // etc
}

错误消息如下

System.Data.Entity.Core.EntityCommandExecutionException was unhandled
  HResult=-2146232004
  Message=An error occurred while executing the command definition. See the inner exception for details.
  Source=EntityFramework
  StackTrace:
       at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
       at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
       at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
       at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
       at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
       at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at SyriusData.LoggedEntityRepositoryBase`1.GetList(Func`2 where, Expression`1[] navigationProperties) in e:\EShared\Dev2013SyriusTest\SyriusTest\SyriusData\LoggedEntityRepositoryBase.cs:line 87
       at SyriusTest.Form1.GetTaskData() in e:\EShared\Dev2013SyriusTest\SyriusTest\SyriusTest\Form1.cs:line 56
       at SyriusTest.Form1.button1_Click(Object sender, EventArgs e) in e:\EShared\Dev2013SyriusTest\SyriusTest\SyriusTest\Form1.cs:line 41
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at SyriusTest.Program.Main() in e:\EShared\Dev2013SyriusTest\SyriusTest\SyriusTest\Program.cs:line 19
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.Data.SqlClient.SqlException
       HResult=-2146232060
       Message=Invalid column name 'TemplateTask_Id'.
       Source=.Net SqlClient Data Provider
       ErrorCode=-2146232060
       Class=16
       LineNumber=29
       Number=207
       Procedure=""
       Server=Myserver\SQL2008R2
       State=1
       StackTrace:
            at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
            at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
            at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
            at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
            at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
            at System.Data.SqlClient.SqlDataReader.get_MetaData()
            at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
            at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
            at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
            at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
            at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
            at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
            at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
            at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)
            at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
            at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
            at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
            at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
            at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)

[更新]我想知道错误是否是由于未遵循EF的命名约定引起的。 如此处所示我认为我已经在TemplateTaskConfiguration类中处理了该问题

问题是我的TemplateContext类没有设置TemplateTaskConfiguration。

我已经在用于创建数据库的主上下文中完成了此操作,但是我忘记了,如果实现了多个上下文,那么它们都需要实现modelBuilder规则。

我的TemplateContext类现在读取

public class TemplateContext : ContextBase<TemplateContext>, ITemplateContext
{
    public DbSet<Template> Templates { get; set; }
    public DbSet<TemplateTask> TemplateTasks { get; set; }
    public DbSet<TemplateTaskDependancy> TemplateTaskDependancies { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Configurations.Add(new TemplateTaskConfiguration());
    }
}

尽管现在看来很明显,但我还是整天都在努力解决这个问题!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM