У меня есть эта модель ExpenseReport
public class ExpenseReport
{
public Guid Id { get; set; }
public Guid InternalId { get; set; }
public Guid AccountId { get; set; }
public string Alias { get; set; }
public bool IsDraft { get; set; }
public int BaseCurrencyId { get; set; }
public Guid ContactId { get; set; }
public Contact Contact { get; set; }
public Guid? JobId { get; set; }
public Job Job { get; set; }
public Customer Customer { get; set; }
public Guid CustomerId { get; set; }
public DateTime? PublishedOn { get; set; }
public DateTime? ExpectedPayDate { get; set; }
public ExpenseReportStatus Status { get; set; }
public ExpenseReportStatusEnum StatusId { get; set; }
public string OriginReference { get; set; }
public decimal AdvanceValue { get; set; }
public decimal TotalValue { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedOn { get; set; }
}
Мне нужно присоединиться, чтобы получить JOB, CUSTOMER,
и Contact
с другого стола
когда я использую LINQ
для получения этих значений, он возвращает мне null
их. Что было бы соединением этого возвращения
Мой запрос
public IQueryable<ExpenseReport> ExpenseReports => (from exReport in _dataContext.ExpenseReport
join job in _dataContext.Job on exReport.JobId equals job.Id
join contact in _dataContext.Contact on exReport.ContactId equals contact.Id
join customer in _dataContext.Customer on exReport.CustomerId equals customer.Id
select exReport );
Я использую EntityFramework с SQL-сервером
Если вы используете EntityFramework, вам НИКОГДА не следует использовать ключевое слово join. Ваш EDM должен быть настроен таким образом, чтобы ваш класс ExpenseReport
имел свойство навигации ExpenseReport.Job
, ExpenseReport.Customer
и ExpenseReport.Contact
. Кроме того, ваш Linq неверен в том, что вы выбираете только ExpenseReport
. В терминах SQL вы делаете Select A.* from A join B on...
.
Что может быть лучше, чтобы принести данные, без того, чтобы я разоблачил то же самое. Нужно ли мне указывать только JOBNAME, нужно ли использовать INCLUDE и использовать только свойство Name?
Зависит от того, где вы пишете свой код. Для правильного повторного использования любой библиотечный код должен просто возвращать IQueryable<ExpenseReport>
. Только в бизнес-логике потребителя вы должны делать проекцию на ExpenseReport.Job.Name
, возможно, с анонимным классом.
настройка выполняется в configEntity. Мое бизнес-правило заключается в том, чтобы приводить только несколько полей работы, таких как имя и идентификатор. Потому что не могу выставить даоды. Я застрял. Я не знаю, правильно ли это .Include(x => x.Job).Select(обязательно)
Давайте продолжить обсуждение в чате.
неверно, что вы никогда не должны использовать ключевое слово join. ключевое слово соединения (или метод расширения) — это самый простой способ реализовать внутреннее соединение или объединить столбцы, которые не являются ключами. Однако для наиболее вероятных требуемых левых внешних соединений на FK=PK «ручное» соединение не требуется.
Вы можете просто сделать следующее в своем бизнес-классе
var results = from report in _context.ExpenseReport
select new { Report = report, JobName = report.Job.Name };
foreach(var x in results)
{
Console.WriteLine($"Got job {x.JobName} with { x.Report }");
}
Мое решение состояло в том, чтобы создать DTO
, который возвращает только то, что мне нужно, и использовать .Include
var ownerData = _repository.ExpenseReports
.Where(w => w.AccountId.Equals(_identityService.Identity.CurrentAccount.Id))
.Include(x => x.Customer)
.Include(x => x.Job)
.Select(x => new MyExpenseReportDTO
{
Id = x.Id,
InternalId = x.InternalId,
Alias = x.Alias,
Job = x.Job.Name,
CreatedOn = x.CreatedOn,
ExpectedPayDate = x.ExpectedPayDate,
Customer = x.Customer.Name,
CostCenterName = x.Job.CostCenter.Name,
BaseCurrencyId = x.BaseCurrencyId,
Status = x.Status.Name,
TotalValue = x.TotalValue
});
Да, IMO с использованием DTO в большинстве случаев является лучшим выбором. Обратите внимание, что из-за Select
Includes
теперь избыточны.
Неясно, какую реализацию
IQueryable
вы используете. Ответ зависит от того, используете ли выEntityFramework
,Linq2SQL
,nHibernate
,OData
и т. д.