Может ли первая кодовая структура Entity Framework выполнять кросс-запросы базы данных с базами данных SQL Server в одном окне?

Я знаю, что было много вопросов о Entity Framework, выполняющих кросс-запросы к базе данных на том же сервере, что и в qaru.site/info/396200/.... В основном ответ кажется "нет", и эта ссылка из возвращается в 2008 году. Тем не менее, Entity Framework меняет все время и на CTP5, мне интересно, остается ли тот же ответ, что вы не можете это сделать, или можете сделать это, если вручную отредактируете файл edmx или у вас есть для использования представлений. Эта особенность сама по себе является причиной того, что я все еще привязан к Linq-to-SQL, так как у нас есть несколько баз данных SQL Server 2008 на одном сервере и вам нужно запросить их. Загрязнение наших баз данных сотнями представлений select * не является вариантом, и с кодовой разработкой у меня нет файла edmx для редактирования. Я играл с базой пабов, чтобы посмотреть, могу ли я где-нибудь попасть, но я застрял. Любые предложения?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;

namespace DbSchema {
    public class Employee {
        [Key]
        public string ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public short JobID { get; set; }
        public Job Job { get; set; }
    }

    public class Job {
        [Key]
        public short ID { get; set; }
        public string Description { get; set; }
    }

    public class PubsRepository : DbContext {
        public DbSet<Employee> Employee { get; set; }
        public DbSet<Job> Job { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            // employee
            var eeMap = modelBuilder.Entity<Employee>();
            eeMap.ToTable("employee", "dbo"); // <-- how do I reference another database?
            eeMap.Property(e => e.ID).HasColumnName("emp_id");
            eeMap.Property(e => e.FirstName).HasColumnName("fname");
            eeMap.Property(e => e.LastName).HasColumnName("lname");
            eeMap.Property(e => e.JobID).HasColumnName("job_id");

            // job
            var jobMap = modelBuilder.Entity<Job>();
            jobMap.Property(j => j.ID).HasColumnName("job_id");
            jobMap.Property(j => j.Description).HasColumnName("job_desc");
        }

        public List<Employee> GetManagers() {
            var qry = this.Employee.Where(x => x.Job.Description.Contains("manager"));
            Debug.WriteLine(qry.ToString());
            return qry.ToList(); // <-- error here when referencing another database!
        }
    }
}

Ответы

Ответ 1

Я думаю, что ответа по-прежнему нет, но есть способы обойти его.

Причина, по которой это не так, заключается в том, что EF использует DBC-контекст, а контекст имеет строку подключения, а строка подключения - в базу данных.

Вот два способа обойти это:

  • используйте два разных контекста по одному для каждой базы данных, это будет означать перенос данных клиенту и объединение его на клиенте.
  • использовать связанные таблицы в базе данных, вытягивая данные через представления, так что EF видит, что он поступает из одной базы данных.

В вашем коде похоже, что вы используете 2 dbcontexts

Ответ 2

Есть два способа сделать это.

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

Другим было создание одного и того же представления запросов кросс-базы в самой модели, создав DefiningQuery. Это наиболее похоже на то, как вы это сделаете с помощью SQLClient. В SQLClient вы должны создать представление в T-SQL как текст SQLCommand, а затем выполнить команду для создания считывателя данных или таблицы данных. Здесь вы используете один и тот же T-SQL для создания DefiningQuery, а затем связываете его с Entity, созданным вручную. Это небольшая работа, но она делает именно то, что вы хотите.

Здесь ссылка на использование DefiningQuerys: http://msdn.microsoft.com/en-us/library/cc982038.aspx.

Если у вас есть книга "" Программирование сущности" Лермана из O'Reilly, там хороший пример в главе 16.

Итак, вам нужно перепрыгнуть через несколько обручей, чтобы делать то, что вы делали непосредственно с SQLClient, НО вы получаете смоделированную Entity.

Ответ 3

Ответ все тот же. Если вы хотите выполнить запрос кросс-базы данных, вы должны вернуться к SQL и использовать SqlQuery в context.Database.

Ответ 4

Внимание! использование DefiningQuerys может быть ОЧЕНЬ МЕДЛЕННО!

Вот пример:

Если это определяющий запрос, создающий объект Entity:

Select
    C.CustomerID,
    C.FirstName,
    C.LastName,
    G.SalesCatetory
From
    CustomerDatabase.dbo.Customers C
    Inner Join MarketingDatabase.dbo.CustomerCategories G on G.CustomerID = C.CustomerID

Затем, когда вы делаете выделение против Entity по идентификатору CustomerID, трассировка SQL выглядит примерно так:

Select
[Extent1].[CustomerID] as [CustomerID],
[Extent1].[FirstName] as [FirstName],
[Extent1].[LastName] as [LastName],
[Extent1].[SalesCatetory] as [SalesCatetory]
From (
        Select
            C.CustomerID,
            C.FirstName,
            C.LastName,
            G.SalesCatetory
        From
            CustomerDatabase.dbo.Customers C
            Inner Join MarketingDatabase.dbo.CustomerCategories G on G.CustomerID = C.CustomerID
        ) as [Extent1]
Where '123456' = [Extent1].[CustomerID]

SQL Server может запускать этот запрос очень медленно. У меня был один случай, немного сложнее, чем приведенный выше пример, где я попытался использовать текст DefiningQuery непосредственно в окне запроса консоли управления SQl Server, добавив предложение where для значения, которое я хотел выбрать. Он работает менее чем за секунду. Затем я захватил SQL Trace для выбора для того же значения из Entity, созданного для этого DefiningQuery, и запускал запрос SQL Trace в окне запроса SQL Server - это заняло 13 секунд!

Итак, я предполагаю, что только реальный способ выполнения кросс-запросов базы данных - создать вейв на сервере.