Подтвердить что ты не робот

Entity Framework 5 вначале не создает базу данных

Я пытаюсь создать новую базу данных, используя первую концепцию кода Entity Framework. Однако при запуске кода база данных не создается (используя параметр DropCreateDatabaseIfModelChanges), хотя код работает нормально. Я вижу следующее исключение, когда пытаюсь получить что-то из базы данных.

enter image description here

Мой проект настраивается с использованием отдельного слоя DataAccess с общей конструкцией сервиса и хранилища. Таким образом, все мои сущности, репозиторий и контекст базы данных находятся в отдельном проекте в рамках решения.

Мой global.asax файл содержит следующий фрагмент кода.

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());

Это должно инициализировать новую базу данных, если ее нет, правильно?

Мой класс контекста базы данных выглядит следующим образом:

namespace Website.DAL.Model
{
    public class MyContext : DbContext
    {
        public IDbSet<Project> Projects { get; set; }
        public IDbSet<Portfolio> Portfolios { get; set; }

        /// <summary>
        /// The constructor, we provide the connectionstring to be used to it base class.
        /// </summary>
        public MyContext()
            : base("MyConnectionString")
        {
        }

        static MyContext()
        {
            try
            {
                Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// This method prevents the plurarization of table names
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
        }
    }
}

Я создал этот класс, следуя нескольким учебникам и статьям в Интернете. Все это ново для меня, но насколько я вижу, все кажется правильным до сих пор. Итак, теперь два объекта, которые я использую. Их называют "Проект" и "Портфолио". Они выглядят так:

public class Portfolio
    {
        [Key]
        public Guid Id { get; set; }
        public String Name { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime? EndDate { get; set; }
        public bool IsPublished { get; set; }

        public virtual ICollection<Project> Projects { get; set; }
    }

и

public class Project 
    {
        [Key]
        public Guid Id { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime? EndDate { get; set; }
        public bool IsPublished { get; set; }
        public String Title { get; set; }
    }

База данных, которую я использую, работает на внешнем сервере, она поставляется с хостинг-провайдером, который я использую. У меня есть база данных SQL Server, и строка подключения к базе данных находится в web.config проекта веб-сайта. Я уже попытался удалить базу данных и позволить ее воссоздать, что, к сожалению, не сработало. Я пропустил что-то очевидное здесь? Или это может быть просто, как права доступа к серверу для создания баз данных?

Примечание. Когда я запускаю команду Database-Update -Script для генерации кода SQL, кажется, что создаются правильные операторы SQL для создания всех таблиц.

ОБНОВЛЕНИЕ 1: Хорошо, благодаря некоторым комментариям я пришел немного дальше. Я добавил два свойства для своих объектов, чтобы внести некоторые изменения, и также создал пользовательский инициализатор, например:

public class ForceDeleteInitializer : IDatabaseInitializer<MyContext>
    {
        private readonly IDatabaseInitializer<MyContext> _initializer = new DropCreateDatabaseIfModelChanges<MyContext>();

        public ForceDeleteInitializer()
        {
            //_initializer = new ForceDeleteInitializer();
        }

        public void InitializeDatabase(MyContext context)
        {
            //This command is added to prevent open connections. See http://stackoverflow.com/info/5288996/database-in-use-error-with-entity-framework-4-code-first
            context.Database.ExecuteSqlCommand("ALTER DATABASE borloOntwikkel SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
            _initializer.InitializeDatabase(context);
        }
    }

Я также удалил инициализатор из конструктора моего контекста, так что это означает, что я удаляю эту строку кода;

Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());

После этого я добавил эти три строки в мой файл Global.asax;

Database.SetInitializer(new ForceDeleteInitializer());
MyContext c = new MyContext();
c.Database.Initialize(true);

При отладке я получаю это исключение; enter image description here

Это дает мне следующую информацию:

  • InnerException говорит: поставщик не возвратил ProviderManifestToken
  • InnerException в InnerException говорит: "Для этой операции требуется подключение к базе masterdatabase. Соединение не может быть сделал ширину "основной" базы данных, поскольку исходное соединение и ссылки были удалены из соединения. Предоставьте не открытое соединение "

После этих действий база данных недоступна, поэтому, скорее всего, она удалена.

Что можно сделать по этому поводу? Скорее всего, я не могу получить доступ к основной базе данных, потому что мой хостинг-провайдер не даст мне надлежащего права на доступ.

4b9b3361

Ответ 1

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

Сначала я создал базу данных и убедился, что правильный пользователь SQL настроен, и у меня был доступ.

Затем я удалил инициализатор и код из файла Global.asax. После этого я запустил следующую команду в консоли диспетчера пакетов (так как многоуровневый дизайн мне нужно было выбрать правильный проект в консоли);

Enable-Migrations

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

Add-Migration AddSortOrder

После того, как мои миграции были созданы, я выполнил следующую команду в консоли и воеле, база данных была обновлена ​​моими сущностями;

Update-Database -Verbose

Чтобы иметь возможность посеять базу данных при выполнении миграции, я переопределил метод Seed в моем классе Configuraton.cs, который был создан при включении миграции. Окончательный код в этом методе выглядит следующим образом:

protected override void Seed(MyContext context)
        {
            //  This method will be called after migrating to the latest version.

            //Add menu items and pages
            if (!context.Menu.Any() && !context.Page.Any())
            {
                context.Menu.AddOrUpdate(new Menu()
                                             {
                                                 Id = Guid.NewGuid(),
                                                 Name = "MainMenu",
                                                 Description = "Some menu",
                                                 IsDeleted = false,
                                                 IsPublished = true,
                                                 PublishStart = DateTime.Now,
                                                 LastModified = DateTime.Now,
                                                 PublishEnd = null,
                                                 MenuItems = new List<MenuItem>()
                                                                 {
                                                                     new MenuItem()
                                                                         {
                                                                             Id = Guid.NewGuid(),
                                                                             IsDeleted = false,
                                                                             IsPublished = true,
                                                                             PublishStart = DateTime.Now,
                                                                             LastModified = DateTime.Now,
                                                                             PublishEnd = null,
                                                                             Name = "Some menuitem",
                                                                             Page = new Page()
                                                                                        {
                                                                                            Id = Guid.NewGuid(),
                                                                                            ActionName = "Some Action",
                                                                                            ControllerName = "SomeController",
                                                                                            IsPublished = true,
                                                                                            IsDeleted = false,
                                                                                            PublishStart = DateTime.Now,
                                                                                            LastModified = DateTime.Now,
                                                                                            PublishEnd = null,
                                                                                            Title = "Some Page"
                                                                                        }
                                                                         },
                                                                     new MenuItem()
                                                                         {
                                                                             Id = Guid.NewGuid(),
                                                                             IsDeleted = false,
                                                                             IsPublished = true,
                                                                             PublishStart = DateTime.Now,
                                                                             LastModified = DateTime.Now,
                                                                             PublishEnd = null,
                                                                             Name = "Some MenuItem",
                                                                             Page = new Page()
                                                                                        {
                                                                                            Id = Guid.NewGuid(),
                                                                                            ActionName = "Some Action",
                                                                                            ControllerName = "SomeController",
                                                                                            IsPublished = true,
                                                                                            IsDeleted = false,
                                                                                            PublishStart = DateTime.Now,
                                                                                            LastModified = DateTime.Now,
                                                                                            PublishEnd = null,
                                                                                            Title = "Some Page"
                                                                                        }
                                                                         }
                                                                 }
                                             });
            }

            if (!context.ComponentType.Any())
            {
                context.ComponentType.AddOrUpdate(new ComponentType()
                {
                    Id = Guid.NewGuid(),
                    IsDeleted = false,
                    IsPublished = true,
                    LastModified = DateTime.Now,
                    Name = "MyComponent",
                    PublishEnd = null,
                    PublishStart = DateTime.Now
                });
            }


            try
            {
                // Your code...
                // Could also be before try if you know the exception occurs in SaveChanges

                context.SaveChanges();
            }
            catch (DbEntityValidationException e)
            {
                //foreach (var eve in e.EntityValidationErrors)
                //{
                //    Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                //        eve.Entry.Entity.GetType().Name, eve.Entry.State);
                //    foreach (var ve in eve.ValidationErrors)
                //    {
                //        Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                //            ve.PropertyName, ve.ErrorMessage);
                //    }
                //}
                //throw;

                var outputLines = new List<string>();
                foreach (var eve in e.EntityValidationErrors)
                {
                    outputLines.Add(string.Format(
                        "{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:",
                        DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        outputLines.Add(string.Format(
                            "- Property: \"{0}\", Error: \"{1}\"",
                            ve.PropertyName, ve.ErrorMessage));
                    }
                }
                System.IO.File.AppendAllLines(@"c:\temp\errors.txt", outputLines);
                throw;
            }
        }

В настоящее время недостатком является то, что мне приходится вручную переносить (только) 2 команды в консоли диспетчера пакетов. Но в то же время факт, что это не происходит динамически, также хорош, потому что это предотвращает возможные изменения моей базы данных. Далее все работает просто отлично.

Ответ 2

+1 для подробного вопроса.

Убедитесь, что ваша строка подключения указывает на правильную базу данных и добавляет атрибуты авторизации, подобные этому, для доступа к вашей базе данных:

<add name="PatientContext" providerName="System.Data.SqlClient" connectionString="Server=SQLSERVER2; Database=Patients; uid=PatientUser; password=123456; Integrated Security=False;" />

Ответ 3

befor intialize его запустить следующий код для создания вашей базы данных:

context.Database.CreateIfNotExists();