Я ценю, если вы могли бы помочь мне понять, почему ObjectDisposedException выбрасывается, когда я удаляю проверку lodging.DestinationId != 0
с DbContext.ValidateLodging()
, приведенную ниже.
Пользовательская проверка в DbContext.ValidateEntity throws ObjectDisposedException
Образец кода, приведенный ниже, представляет собой Программирование Entity Framework от Julie - DbContext, и его можно использовать для воспроизведения исключения.
Окружающая среда: Visual Studio 2012 с Entity Framework 6.0.2
РЕДАКТИРОВАНИЕ 7/1: Включено StackTrace из ObjectDisposedException.
DbContext реализация & тестовых данных
namespace DataAccess
{
public class BagaContext : DbContext
{
public DbSet<Destination> Destinations { get; set; }
public DbSet<Lodging> Lodgings { get; set; }
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var result = base.ValidateEntity(entityEntry, items);
if (result.IsValid)
{
ValidateLodging(result);
}
return result;
}
private void ValidateLodging(DbEntityValidationResult result)
{
var lodging = result.Entry.Entity as Lodging;
// PROBLEM: Removing lodging.DestinationId != 0 causes ObjectDisposedException.
if (lodging != null && lodging.DestinationId != 0)
{
if (Lodgings.Any(l => l.Name == lodging.Name &&
l.DestinationId == lodging.DestinationId))
{
result.ValidationErrors.Add(
new DbValidationError(
"Lodging",
"There is already a lodging named " + lodging.Name +
" at this destination.")
);
}
}
}
public BagaContext()
{
Database.SetInitializer<BagaContext>(new InitializeBagaDatabaseWithSeedData());
}
}
public class InitializeBagaDatabaseWithSeedData : DropCreateDatabaseAlways<BagaContext>
{
protected override void Seed(BagaContext context)
{
context.Destinations.Add(new Destination
{
Name = "Grand Canyon",
Lodgings = new List<Lodging>
{
new Lodging {Name = "Grand Hotel"},
new Lodging {Name = "Dave's Dump"}
}
});
}
}
}
Код для проверки реализации DbContext.ValidateEntity
namespace Client
{
class Program
{
static void Main(string[] args)
{
CreateDuplicateLodging();
Console.ReadLine();
}
private static void CreateDuplicateLodging()
{
using (var context = new BagaContext())
{
var destination = context.Destinations.FirstOrDefault(d => d.Name == "Grand Canyon");
try
{
context.Lodgings.Add(new Lodging
{
Destination = destination,
Name = "Grand Hotel"
});
context.SaveChanges();
Console.WriteLine("Save Successful");
}
catch (DbEntityValidationException ex)
{
Console.WriteLine("Save Failed: ");
foreach (var error in ex.EntityValidationErrors)
{
Console.WriteLine(
string.Join(Environment.NewLine,
error.ValidationErrors.Select(v => v.ErrorMessage)));
}
}
}
}
}
}
Модель классы
namespace Model
{
[Table("Locations", Schema = "baga")]
public class Destination
{
public Destination()
{
this.Lodgings = new List<Lodging>();
}
[Column("LocationID")]
public int DestinationId { get; set; }
[Required, Column("LocationName")]
[MaxLength(200)]
public string Name { get; set; }
public virtual List<Lodging> Lodgings { get; set; }
}
public class Lodging
{
public int LodgingId { get; set; }
[Required]
[MaxLength(200)]
[MinLength(10)]
public string Name { get; set; }
[Column("destination_id")]
public int DestinationId { get; set; }
public Destination Destination { get; set; }
}
}
StackTrace из ObjectDisposedException
at System.Data.Entity.Core.Objects.ObjectContext.get_Connection()
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.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3[TResult](IEnumerable`1 sequence)
at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Any[TSource](IQueryable`1 source, Expression`1 predicate)
at DataAccess.BagaContext.ValidateLodging(DbEntityValidationResult result) in c:\Users\User\Documents\Visual Studio 2012\Projects\Learning\EF\StackOverflowQuestions\DataAccess\BreakAwayContext.cs:line 38
at DataAccess.BagaContext.ValidateEntity(DbEntityEntry entityEntry, IDictionary`2 items) in c:\Users\User\Documents\Visual Studio 2012\Projects\Learning\EF\StackOverflowQuestions\DataAccess\BreakAwayContext.cs:line 26
at System.Data.Entity.DbContext.GetValidationErrors()
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at Client.Program.CreateDuplicateLodging() in c:\Users\User\Documents\Visual Studio 2012\Projects\Learning\EF\StackOverflowQuestions\Client\Program.cs:line 34
at Client.Program.Main(String[] args) in c:\Users\User\Documents\Visual Studio 2012\Projects\Learning\EF\StackOverflowQuestions\Client\Program.cs:line 18
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()
Спасибо.
Можете ли вы включить трассировку стека объекта ObjectDisposedException? –
@SteveRuble: добавлен StackTrace. Благодарю. – RanC
'lodging.DestinationId! = 0' - это красная селедка (DestinationId всегда будет 0, потому что вы только установили' lodging.Destination' и экземпляр 'Lodging' не проксирован (т. Е. Вы создали его с' new' так что это POCO, у которого нет логики для установки 'DestinationId', когда установлено свойство« Destination »)). Вместо этого вы должны проверить 'lodging.Destination! = Null'. Однако это не объясняет исключение. Я все еще пытаюсь понять это (я думаю, что это как-то связано с выдачей запроса из системы проверки). –