Entity Framework Code First, не генерирующая базу данных - PullRequest
3 голосов
/ 25 февраля 2012

Я совершенно новичок в использовании кода в первую очередь для моделирования баз данных. Я пытался следовать нескольким различным учебникам и сталкиваться с проблемами со всеми из них, и никогда не могу понять, почему.

Сейчас у меня есть новый проект MVC 4. Я работаю над этим проектом с 3 другими, и мы используем Team Foundation Server для контроля версий. Следуя различным урокам, я настроил свои модели так:

public class User
{
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }

    public virtual ICollection<Entry> Entries { get; set; }
    public virtual ICollection<Rating> Ratings { get; set; }
}

public class Contest
{
    public int ContestId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public Boolean Published { get; set; }

    public virtual ICollection<Submission> Submissions { get; set; }
    public virtual ICollection<Tab> Tabs { get; set; }
}

public class Tab
{
    public int TabId { get; set; }
    public string Name { get; set; }
    public int Order { get; set; }
    public string Content { get; set; }
    public int ContestId { get; set; }

public virtual Contest Contest { get; set; }
}

public class Entry
{
    public int EntryId { get; set; }
    public string Title { get; set; }
    public string EmbedURL { get; set; }
    public string Description { get; set; }
    public Boolean isApproved { get; set; }
    public int UserId { get; set; }

    public virtual ICollection<Submission> Submissions { get; set; }

    public virtual User User { get; set; }
}

public class Submission
{
    public int SubmissionId { get; set; }
    public DateTime Submitted { get; set; }
    public int EntryId { get; set; }
    public int ContestId { get; set; }

    public virtual Entry Entry { get; set; }
    public virtual Contest Contest { get; set; }
}

public class Rating
{
    public int RatingId { get; set; }
    public int Stars { get; set; }
    public int UserId { get; set; }
    public int SubmissionId { get; set; }


    public virtual User User { get; set; }
    public virtual Submission Submission { get; set; }
}

и создал расширение DbContext:

public class CPContext : DbContext
{
    public CPContext() : base("name=CPContext")
    {
    }

    public DbSet<Contest> Contests { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<Entry> Entries { get; set; }
    public DbSet<Submission> Submissions { get; set; }
    public DbSet<Rating> Ratings { get; set; }
    public DbSet<Tab> Tabs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Наконец, строка подключения в моем файле Web.config:

<add name="CPContext" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=aspnet_ContestPlatform;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />

В дополнение ко всему, я инициализирую свою базу данных с данными теста ниже:

//Will seed the database with dummy values when accessed for first time
public class ContestPlatformInitializer : DropCreateDatabaseIfModelChanges<CPContext>
{
    protected override void Seed(CPContext context)
    {
        var users = new List<User>
        {
            new User { FirstName = "Daniel", LastName = "Hines", Email = "hinesd@blah.edu" },
            new User { FirstName = "Peter", LastName = "Pan", Email = "panp@blah.edu" },
            new User { FirstName = "Marie", LastName = "VerMurlen", Email = "vermurle@blah.edu" },
            new User { FirstName = "Aaron", LastName = "Brown", Email = "browna5@blah.edu" }
        };
        users.ForEach(s => context.Users.Add(s));
        context.SaveChanges();

        var entries = new List<Entry>
        {
            new Entry { UserId = 1, Title = "Flight Simulation", EmbedURL = "www.blah.com/video1", Description = "This is an awesome app!", isApproved = true },
            new Entry { UserId = 2, Title = "Underwater Explorer", EmbedURL = "www.blah.com/video1", Description = "This is an awesome app!!", isApproved = true },
            new Entry { UserId = 3, Title = "Dress-Up", EmbedURL = "www.blah.com/video1", Description = "This is an awesome app!!!", isApproved = true },
            new Entry { UserId = 4, Title = "Combat Training", EmbedURL = "www.blah.com/video1", Description = "This is an awesome app!!!!", isApproved = true },
            new Entry { UserId = 1, Title = "Fitness Pro", EmbedURL = "www.blah.com/video1", Description = "This is an awesome app!!!!!", isApproved = true }
        };
        entries.ForEach(s => context.Entries.Add(s));
        context.SaveChanges();

        var contests = new List<Contest>
        {
            new Contest { Name = "Game Contest", Description = "This contest is to see who can make the most awesome game!", Start = DateTime.Parse("2012-02-10"), End = DateTime.Parse("2012-04-20"), Published = true },
            new Contest { Name = "App Contest", Description = "This contest is to see who can make the coolest app!", Start = DateTime.Parse("2012-03-10"), End = DateTime.Parse("2012-09-20"), Published = false }
        };
        contests.ForEach(s => context.Contests.Add(s));
        context.SaveChanges();

        var tabs = new List<Tab>
        {
            new Tab { ContestId = 1, Name = "Rules", Content = "The first rule is that there are no rules!", Order = 1 },
            new Tab { ContestId = 2, Name = "Examples", Content = "No examples here yet, check back soon.", Order = 1}
        };
        tabs.ForEach(s => context.Tabs.Add(s));
        context.SaveChanges();

        var submissions = new List<Submission>
        {
            new Submission { ContestId = 1, EntryId = 1, Submitted = DateTime.Parse("2-13-2012") },
            new Submission { ContestId = 1, EntryId = 2, Submitted = DateTime.Parse("2-14-2012") },
            new Submission { ContestId = 1, EntryId = 3, Submitted = DateTime.Parse("2-15-2012") },
            new Submission { ContestId = 1, EntryId = 4, Submitted = DateTime.Parse("2-16-2012") },
        };
        submissions.ForEach(s => context.Submissions.Add(s));
        context.SaveChanges();

        var ratings = new List<Rating>
        {
            new Rating { Stars = 4, UserId = 1, SubmissionId = 1 },
            new Rating { Stars = 5, UserId = 2, SubmissionId = 1 },
            new Rating { Stars = 2, UserId = 3, SubmissionId = 1 },
            new Rating { Stars = 4, UserId = 4, SubmissionId = 1 },

            new Rating { Stars = 1, UserId = 1, SubmissionId = 2 },
            new Rating { Stars = 2, UserId = 2, SubmissionId = 2 },
            new Rating { Stars = 1, UserId = 3, SubmissionId = 2 },
            new Rating { Stars = 3, UserId = 4, SubmissionId = 2 },

            new Rating { Stars = 5, UserId = 1, SubmissionId = 3 },
            new Rating { Stars = 5, UserId = 2, SubmissionId = 3 },
            new Rating { Stars = 4, UserId = 3, SubmissionId = 3 }
        };
        ratings.ForEach(s => context.Ratings.Add(s));
        context.SaveChanges();
    }
}

, который вызывается в моем методе Application_Start () в моем файле Global.asax.

Итак, теперь, чтобы проверить, что все работает правильно, я создал контроллер для моей модели Contest, который сгенерировал соответствующее представление. Когда я компилирую свое приложение и пытаюсь вызвать контроллер контеста, возникает исключение.

System.Data.EntityCommandExecutionException не был обработан кодом пользователя Сообщение = Произошла ошибка при выполнении определения команды. Смотрите внутреннее исключение для деталей. Источник = System.Data.Entity Трассировки стека: в System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, поведение CommandBehavior) в System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute [TResultType] (контекст ObjectContext, ObjectParameterCollection parameterValues) в System.Data.Objects.ObjectQuery 1.GetResults(Nullable 1 forMergeOption) в System.Data.Objects.ObjectQuery 1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at System.Collections.Generic.List 1..ctor (источник IEnumerable 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable 1) в ContestPlatform.Controllers.ContestController.Index () в C: \ Users \ Danny \ Documents \ Visual Studio 2010 \ Projects \ ContestPlatform \ ContestPlatform \ ContestPlatform \ Controllers \ ContestController.cs: строка 21 at lambda_method (Closure, ControllerBase, Object []) в System.Web.Mvc.ReflectedActionDescriptor.Execute (ControllerContext controllerContext, IDictionary`2 параметры) на System.Web.Mvc.Async.AsyncControllerActionInvoker. <> c_ DisplayClass42.b _41 () на System.Web.Mvc.Async.AsyncControllerActionInvoker. <> c_ DisplayClass37. <> c _DisplayClass39.b_ 33 () на System.Web.Mvc.Async.AsyncControllerActionInvoker. <> c _DisplayClass4f.b__49 () InnerException: System.Data.SqlClient.SqlException Сообщение = Неверное имя объекта 'dbo.Contest'. Источник = .Net SqlClient Data Provider ErrorCode = -2146232060 Класс = 16 LineNumber = 1 Number = 208 Процедура = «» Server =. \ SQLEXPRESS State = 1 Трассировки стека: в System.Data.SqlClient.SqlConnection.OnError (исключение SqlException, логическое breakConnection) в System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning () в System.Data.SqlClient.TdsParser.Run (RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) в System.Data.SqlClient.SqlDataReader.ConsumeMetaData () в System.Data.SqlClient.SqlDataReader.get_MetaData () в System.Data.SqlClient.SqlCommand.FinishExecuteReader (SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) в System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, RunBehavior runBehavior, логический returnStream, логический асинхронный) в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, логический returnStream, метод String, результат DbAsyncResult) в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, логический returnStream, метод String)в System.Data.SqlClient.SqlCommand.ExecuteReader (поведение CommandBehavior, метод String) в System.Data.SqlClient.SqlCommand.ExecuteDbDataReader (поведение CommandBehavior) в System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, поведение CommandBehavior) InnerException:

Заметив строку «Сообщение = Неверное имя объекта« dbo.Contest »», я хотел дважды проверить, что таблица dbo.Contest действительно генерируется.

Я могу зайти в Management Studio Express и посмотреть базу данных "aspnet_ContestPlatform", но в ней нет таблиц.

Это база данных, которую я должен увидеть? Почему не создаются таблицы? Кроме того, если нет таблиц, почему я не получаю исключение правильно, когда приложение запускается, когда предполагается, что база данных заполняется тестовыми данными?

1 Ответ

1 голос
/ 25 февраля 2012

Нет, имя базы данных должно быть [YourNamespace, если есть] .CPContext, а не "aspnet_ContestPlatform".

Я думаю, что причина того, что вы не получаете немедленное исключение, заключается в том, что только когда вы нажимаете на представление, которое использует контроллер, который фактически выполняет ваши GetResults для базы данных, она падает. Что-то мешает созданию базы данных - не знаю, что - но пока вы не выбираете ее, в приложении ничего не происходит.

Вы пытались изменить модель и снова запустить приложение? Я часто сохраняю фиктивное свойство для одной из моих второстепенных сущностей, которую я попеременно комментирую / отключаю для регенерации базы данных. Я знаю, что это не лучший способ сделать что-то, но модель меняется, поэтому база данных должна быть удалена и воссоздана.

...