2015-03-08 3 views
1

Я моделирую бизнес-сервис, который выполняет несколько сервисов при каждом посещении клиента. У меня есть таблица «Посещение», таблица «Сервис» и таблица ссылок «VisitService». Я использую этот запрос DTO в моей службе, чтобы получить список услуг для посещения:ServiceStack ORMLite - Не удается определить отношения (из-за имени DTO?)

[Route("/visits/{visitid}/services", Verbs = "GET")] 
    public class ServicesAtVisit : QueryBase<VisitService, ServiceAtVisit>, IJoin<VisitService, My.Namespace.Service> { 
    public int VisitId { get; set; } 
} 

ServiceAtVisit обычая DTO, что я проецирование в.

Поскольку один из моих DTO является классом с неудачным именем «Сервис», я должен полностью квалифицировать его в IJoin, потому что в противном случае он неоднозначен с ServiceStack.Service. Теперь, когда я ударил по маршруту, я получаю сообщение об ошибке «Не удалось установить отношения между VisitService и Service».

Интересно, что у меня это работает с другими отношениями «многие ко многим» (Client.AssignedStaffMembers, StaffMember.AssignedClients для таблиц Client -> ClientStaffMember -> StaffMember), и я не вижу ничего другого ,

Является ли проблема именем моего DTO и тем фактом, что мне нужно полностью квалифицировать его?

визит:

[Route("/visits", Verbs = "POST")] 
public partial class Visit { 
    [AutoIncrement] 
    public long Id { get; set; } 
    public int ServiceRequestId { get; set; } 
    public string TimeOfDay { get; set; } 
    public DateTime Date { get; set; } 
    public TimeSpan? PreferredStartTime { get; set; } 
    public TimeSpan? PreferredEndTime { get; set; } 
    public bool IsFirstVisit { get; set; } 
    public bool IsLastVisit { get; set; } 
    public bool IncursWeekendFee { get; set; } 
    public bool WaiveWeekendFee { get; set; } 
    public bool IncursHolidayFee { get; set; } 
    public bool WaiveHolidayFee { get; set; } 
    public bool IncursLastMinuteSchedulingFee { get; set; } 
    public bool WaiveLastMinuteSchedulingFee { get; set; } 
    public bool IncursLastMinuteCancellationFee { get; set; } 
    public bool WaiveLastMinuteCancellationFee { get; set; } 
    public int? StaffMemberId { get; set; } 
    public string Notes { get; set; } 
    public bool IsCancelled { get; set; } 
    public DateTime? CheckInDateTime { get; set; } 
    public int? CheckInStaffMemberId { get; set; } 
    public DateTime? CheckOutDateTime { get; set; } 
    public int? CheckOutStaffMemberId { get; set; } 

    [Ignore] 
    public ServiceRequest ServiceRequest { get; set; } 

    [Ignore] 
    public StaffMember StaffMember { get; set; } 

    [Ignore] 
    public List<ServiceAtVisit> ServicesAtVisit { get; set; } 
} 

VisitService:

public partial class VisitService { 

    // Workaround for composite key limitation 
    public string Id { 
     get { 
      return this.VisitId.ToString() + "|" + this.ServiceId.ToString(); 
     } 
    } 

    public long VisitId { get; set; } 
    public int ServiceId { get; set; } 
    public int Quantity { get; set; } 
    public bool FeeIsWaived { get; set; } 

    [Ignore] 
    public Visit Visit { get; set; } 

    [Ignore] 
    public Service Service { get; set; } 
} 

Услуги:

public partial class Service { 
    [AutoIncrement] 
    public int Id { get; set; } 
    public int ServiceTypeId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public int DisplayOrder { get; set; } 
    public bool IsHourly { get; set; } 
    public bool IsMonthly { get; set; } 

    [Ignore] 
    public ServiceType ServiceType { get; set; } 

    [Ignore] 
    public ServicePrice CurrentPrice { get; set; } 
} 

проецирование результатов в ServiceAtVisit:

public partial class ServiceAtVisit { 
    public int ServiceTypeId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public int DisplayOrder { get; set; } 
    public bool IsHourly { get; set; } 
    public bool IsMonthly { get; set; } 

    public int VisitId { get; set; } 
    public int ServiceId { get; set; } 
    public int Quantity { get; set; } 
    public bool FeeIsWaived { get; set; } 
} 
+0

просьба предоставить исходный код всех таблиц, которые вы пытаетесь присоединиться. – mythz

+0

Добавлен код - спасибо за то, что посмотрели Demis. – user2220004

ответ

1

Я просто попытался создания AutoQuery службы со всеми типами вы предоставили под обычаем MyNamespace и он работает, как ожидалось (в последней из ServiceStack), а именно:

Определение сервиса:

namespace MyNamespace 
{ 
    [Route("/visits/{VisitId}/services", Verbs = "GET")] 
    public class ServicesAtVisit : QueryBase<VisitService, ServiceAtVisit>, 
     IJoin<VisitService, Service> 
    { 
     public int VisitId { get; set; } 
    } 

    public partial class ServiceAtVisit 
    { 
     public int ServiceTypeId { get; set; } 
     public string Name { get; set; } 
     public string Description { get; set; } 
     public int DisplayOrder { get; set; } 
     public bool IsHourly { get; set; } 
     public bool IsMonthly { get; set; } 

     public int VisitId { get; set; } 
     public int ServiceId { get; set; } 
     public int Quantity { get; set; } 
     public bool FeeIsWaived { get; set; } 
    } 
} 

определение Тип:

namespace MyNamespace 
{ 
    [Route("/visits", Verbs = "POST")] 
    public partial class Visit 
    { 
     [AutoIncrement] 
     public long Id { get; set; } 
     public int ServiceRequestId { get; set; } 
     public string TimeOfDay { get; set; } 
     public DateTime Date { get; set; } 
     public TimeSpan? PreferredStartTime { get; set; } 
     public TimeSpan? PreferredEndTime { get; set; } 
     public bool IsFirstVisit { get; set; } 
     public bool IsLastVisit { get; set; } 
     public bool IncursWeekendFee { get; set; } 
     public bool WaiveWeekendFee { get; set; } 
     public bool IncursHolidayFee { get; set; } 
     public bool WaiveHolidayFee { get; set; } 
     public bool IncursLastMinuteSchedulingFee { get; set; } 
     public bool WaiveLastMinuteSchedulingFee { get; set; } 
     public bool IncursLastMinuteCancellationFee { get; set; } 
     public bool WaiveLastMinuteCancellationFee { get; set; } 
     public int? StaffMemberId { get; set; } 
     public string Notes { get; set; } 
     public bool IsCancelled { get; set; } 
     public DateTime? CheckInDateTime { get; set; } 
     public int? CheckInStaffMemberId { get; set; } 
     public DateTime? CheckOutDateTime { get; set; } 
     public int? CheckOutStaffMemberId { get; set; } 

     //[Ignore] 
     //public ServiceRequest ServiceRequest { get; set; } 

     //[Ignore] 
     //public StaffMember StaffMember { get; set; } 

     [Ignore] 
     public List<ServiceAtVisit> ServicesAtVisit { get; set; } 
    } 

    public partial class VisitService 
    { 
     // Workaround for composite key limitation 
     public string Id 
     { 
      get 
      { 
       return this.VisitId.ToString() + "|" + this.ServiceId.ToString(); 
      } 
     } 

     public long VisitId { get; set; } 
     public int ServiceId { get; set; } 
     public int Quantity { get; set; } 
     public bool FeeIsWaived { get; set; } 

     [Ignore] 
     public Visit Visit { get; set; } 

     [Ignore] 
     public Service Service { get; set; } 
    } 

    public partial class Service 
    { 
     [AutoIncrement] 
     public int Id { get; set; } 
     public int ServiceTypeId { get; set; } 
     public string Name { get; set; } 
     public string Description { get; set; } 
     public int DisplayOrder { get; set; } 
     public bool IsHourly { get; set; } 
     public bool IsMonthly { get; set; } 

     //[Ignore] 
     //public ServiceType ServiceType { get; set; } 

     //[Ignore] 
     //public ServicePrice CurrentPrice { get; set; } 
    } 
} 

Тестовые данные:

using (var db = container.Resolve<IDbConnectionFactory>().Open()) 
{ 
    db.DropAndCreateTable<MyNamespace.Visit>(); 
    db.DropAndCreateTable<MyNamespace.VisitService>(); 
    db.DropAndCreateTable<MyNamespace.Service>(); 

    var visitId = db.Insert(new MyNamespace.Visit { 
     Date = DateTime.UtcNow, Notes = "Notes"}, selectIdentity: true); 
    var serviceId = (int)db.Insert(new MyNamespace.Service { 
     ServiceTypeId = 1, Name = "Name"}, selectIdentity:true); 
    db.Insert(new MyNamespace.VisitService { 
     VisitId = visitId, ServiceId = serviceId, Quantity = 1}); 
} 

Сервис Результат:

http://localhost:{port}/visits/1/services.json 

JSON ответ:

{ 
    offset: 0, 
    total: 1, 
    results: [{ 
     serviceTypeId: 1, 
     name: "Name", 
     displayOrder: 0, 
     isHourly: false, 
     isMonthly: false, 
     visitId: 1, 
     serviceId: 1, 
     quantity: 1, 
     feeIsWaived: false 
    }] 
} 
+0

Не уверен, что это имеет значение, но служба и DTO находятся в разных пространствах имен - MyNamespace.WebAPI и MyNamespace.DTO. И поскольку я «использую» ServiceStack и MyNamespace.DTO в сервисе, мой IJoin выглядит как IJoin user2220004

+0

@ user2220004 полностью квалифицирует тип с пространством имен или нет не имеет разницы в скомпилированной программе - он все равно ссылается на один и тот же тип.Я только что использовал типы, которые вы предоставили, которые я добавил на существующий веб-сайт и работает как есть, как показано в примере выше. Это очень маловероятные пространства имен являются причиной ваших проблем, AutoQuery использует только имя типа, чтобы определить, какую таблицу запрашивать, а не пространство имен. – mythz

+1

Спасибо за разъяснение и заставило меня вернуться еще на один серьезный взгляд на это. Оказывается, никогда не должно быть DTO/table под названием «Сервис», если вы хотите написать «сервис», чтобы согласиться с ним. Я ссылался на DTO «VisitService» внутри моей службы ServiceStack для посещений, которые вызывают ... VisitService. Мне понадобилось еще несколько квалификаторов пространства имен: QueryBase , IJoin . Извините за то, что потратил ваше время. – user2220004