Fetching results from more than one IRepository - orchardcms

I have a list of Users and Orders.
public class UserRecord
{
public virtual int UserId { get; set; }
public virtual string Name { get; set; }
}
public class OrderRecord
{
public virtual int UserId { get; set; }
public virtual int OrderId { get; set; }
}
I have two repositories - IRepository and IRepository. How can I join the two and fetch the result, like this?
SELECT UserRecord.UserId, Name, OrderId
FROM UserRecord, OrderRecord
WHERE UserRecord.UserId = OrderRecord.UserId
Thanks.

Use the HQL API that is on ContentManager instead. Repository is for simple CRUD operations on a single table.

Related

Conversion failed,when using AutoQuery in ServiceStack

I have the following AutoQuery function.
[Route("/cars/search")]
public class SearchCars : QueryDb<Car, CarDto>
{
public List<int> EquipmentIds { get; set; }
public List<int> ManufacturerIds { get; set; }
public List<int> ColourIds { get; set; }
}
The function works, when I do the following:
Cars/Search?ColourIds=1&format=json
Cars/Search?ManufacturerIds=1&format=json
but when I try to use
Cars/Search?EquipmentIds=1&format=json
I get "Conversion failed when converting the varchar value '[1]' to data type int.".
The difference between these fields is that Car object can have multiple EquipmentIds, but only one ColourId and ManufacturerId.
public class Car
{
[AutoIncrement]
public int Id { get; set; }
public Colour Colour { get; set; }
[Required]
public int ColourId { get; set; }
public Manufacturer Manufacturer { get; set; }
[Required]
public int ManufacturerId { get; set; }
[Required]
public List<Equipment> Equipment { get; set; }
[Required]
public List<int> EquipmentId { get; set; }
}
Do I have to define for which attribute the different parameters should be assigned too?
AutoQuery works by constructing an RDBMS query based on implicit conventions which is used to construct an SQL query that runs on the RDBMS.
Complex Types in OrmLite data models are blobbed by default which means they can't be queried in the RDBMS with SQL, so you wont be able to query it with AutoQuery.
You could create a hybrid Custom AutoQuery Implementation where you can apply any custom logic to filter the results of the AutoQuery results, something like...
public class MyQueryServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
//Override with custom implementation
public object Any(SearchCars query)
{
var equipmentIds = query.EquipmentIds;
query.EquipmentIds = null;
var q = AutoQuery.CreateQuery(query, base.Request);
var response = AutoQuery.Execute(query, q);
if (equipmentIds != null)
response.Results.RemoveAll(x => x.EquipmentId...);
return response.
}
}

Automapper projection results in empty collection for nested Dto

I have a .Net Core 2 webapi in which I am using automapper to map to Dtos. Everything works fine, except I am seeing an unexpected behaviour when I map an object to a Dto, and where the Dto also contains mappings for a collection. E.g
CreateMap<Order, OrderDto>();
CreateMap<Product, ProductDto>();
Where classes are like this
public partial class Order
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products{ get; set; }
public int ProductCount {return Products.Count;}
}
public partial class Product
{
public int Id { get; set; }
public int OrderId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The following works as expected;
The class is mapped, and the ProjectCount is correct in the Dto
public partial class OrderDto
{
public int Id { get; set; }
public virtual ICollection<Product> Products{ get; set; }
public int ProductCount{ get; set; }
}
_context.Orders.Include<>(Products).ProjectTo<>(OrderDto)
But doing the following, the productcount is always zero.
E.g. if I do this;
public partial class OrderDto
{
public int Id { get; set; }
public virtual ICollection<ProductDto> Products{ get; set; }
public int ProductCount{ get; set; }
}
public partial class ProductDto
{
public int Id { get; set; }
public int OrderId { get; set; }
public string Name { get; set; }
}
_context.Orders.Include<>(Products).ProjectTo<>(OrderDto)
Why does this happen, and how can I ensure that it doesnt? This is a real world example where I need a property which references the collection - and I need it in both the base and the Dto. I can do the following which works fine, but it doesnt appear that this should be how it works...
public partial class OrderDto
{
public int Id { get; set; }
public virtual ICollection<ProductDto> Products{ get; set; }
public int ProductCount {return Products.Count;}
}
public partial class ProductDto
{
public int Id { get; set; }
public string Name { get; set; }
}
_context.Orders.Include<>(Products).ProjectTo<>(OrderDto)
I profiled the SQL and found that Automapper changes the way the query is formed. Without the nested projection, two queries are made;
[Queries are more complex than this and use joins, but you get the idea]
Select Id from orders
Select Id,Name from products where productid in [select id from orders ]
With the nested projection, are executed for each nested Dto
Select Id from orders
Select Id,Name from products where id=1
Select Id,Name from products where id=2

EntityFramework : Invalid column name *_ID1

I am trying to implement DbContext for couple of tables called 'Employee' and 'Department'
Relationship between Employee and Department is many to one. i.e. department can have many employees.
Below are the EntityFramework classes I designed ( CodeFirst approach )
[Table("Employee")]
public class Employee
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Department_ID")]
public int Department_ID { get; set; }
public virtual Department Department { get; set; }
}
[Table("Department")]
public class Department
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Column("Name")]
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
While adding Employee record I am getting below exception
"Invalid column name 'Department_ID1'."
I am not sure why EF is referring to Department_ID1. Do I need to add configuration in OnModelCreating method of DbContext?
I am using EF version 6.1.1
I've also gotten this problem in my EF one-many deals where the one has a List of the many property and my mapping didn't specify that property. For example take:
public class Notification
{
public long ID { get; set; }
public IList<NotificationRecipient> Recipients { get; set; }
}
then
public class NotificationRecipient
{
public long ID { get; set; }
public long NotificationID { get; set; }
public Notification Notification { get; set; }
}
Then in my mapping, the way that caused the Exception (the incorrect way):
builder.HasOne(x => x.Notification).WithMany()
.HasForeignKey(x => x.NotificationID);
What fixed it (the correct way) was specifying the WithMany property:
builder.HasOne(x => x.Notification).WithMany(x => x.Recipients)
.HasForeignKey(x => x.NotificationID);
Hi After spending some time I could fix this problem by using ForeignKey attribute on public virtual Department Department { get; set; } property of Employee class.
Please see below code.
[Table("Employee")]
public class Employee
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Department_ID")]
public int Department_ID { get; set; }
[ForeignKey("Department_ID")]
public virtual Department Department { get; set; }
}
This fixed my problem. Are there any other solution to fix this? Using fluent API?
For me, the issue was resolved by removing a (duplicate?) virtual property.
Using the OP's example:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Department_ID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
Turns into:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Department_ID { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
In my case I added a virtual property on top of the auto generated property
I fixed it by adding the NotMapped attribute to my property, or you could configure with fluent api
public partial class Control
{
[NotMapped]
public virtual ICollection<Control> Children { get => this.InverseParent; set => this.InverseParent = value; }
}
I had the same error, my issue was the FK was a long but I had it as an int in the model. EF generated a new column because it didn't match types on the FK so it assumed they weren't the same and went ahead with making another one but putting 1 at the end because there was already one with the proper name. Making sure the types matched resolved the issue for me.
This can be fixed simply by putting [NotMapped] annotation on your virtual properties.
public class Employee
{
[ForeignKey("Department")]
public int Department_ID
[NotMapped]
public virtual Department Department { get; set; }
}
And in you modelBuilder:
modelBuilder.Entity<Employee>(entity =>
{
entity.HasOne(e => e.Department);
});
Just flip this around if you want to call by Department.
We use the [NotMapped] annotation so that EF Core will disregard it when looking at your database.

MVC using multiple tables , 2 generated with code first and one with DB first

I am new to MVC and i think someone answered this question before , so i apologize for re-posting it.
I've been a form based programmers for years , and now i am working on an MVC project for the first time, last 3 weeks i read a lot of books, articles, tutorials and watched a lot of videos about MVC.
Here is my question:
- I have 3 tables: Tasks, Customer and Employee
Each task has 1 customer and one employee assigned to it. I generated the Tasks table from an existing table i have on a SQL DB , but i followed "Code-First" to create the employee and Customer tables. I am not sure if i did the right relationships between those table. What i want to do is to display all tasks + the userNAME + CustomerName instead of UserID and CustomerID.
Here are my models:
Tasks:
public partial class Tasks
{
public string TaskID { get; set; }
public string Name { get; set; }
public System.DateTime StartDate { get; set; }
public Nullable<System.DateTime> DueDate { get; set; }
public Nullable<int> Complete { get; set; }
public string Description { get; set; }
public Nullable<int> Priority { get; set; }
public string Status { get; set; }
public Nullable<System.DateTime> AssignementDate { get; set; }
public Nullable<System.DateTime> CreationDate { get; set; }
[ForeignKey ("Employee")]
public string EmployeeID { get; set; }
public virtual ApplicationUser _User { get; set; }
[ForeignKey("Customer")]
public string CustomerID { get; set; }
public virtual CustomerModel _Customer { get; set; }
}
Customer:
public class CustomerModel
{
[Key]
public String ID { get; set; }
public String Number { get; set; }
}
Employee
public class EmployeeModel
{
[Key]
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Also How to access the employee first name from my Tasks controller.
Last question: is it ok to mix between models (Some code-first and some DB-first) Or should i follow one pattern.
Thanks a lot
You can use both pattern, but I recommend you my approach that you use CodeFirst, create entites to store data and viewmodels to display data:
public class Task
{
public int TaskID { get; set; }
//your other properties here...
public int EmployeeId { get; set; }
public int UserId { get; set; }
public int CustomerId { get; set; }
}
And in client lawyer, create ViewModel for Task model:
public class TaskViewModel
{
public Task Task { get; set; }
public EmployeeModel Employee { get; set; }
public ApplicationUser User { get; set; }
public CustomerModel Customer { get; set; }
}
In your GetTask() (Or LoadTasks()) method fill this view model:
public TaskViewModel GetTask(int id)
{
TaskViewModel model = new TaskViewModel();
model.Task = _db.GetTaskById(id);
model.Employee = _db.GetEmployeeById(model.Task.EmployeeId);
model.User = _db.GetUserById(model.Task.UserId);
model.Customer = _db.GetCustomerById(model.Task.CustomerId);
return model;
}
And now, you can get all data you want related to a task:
TaskId, TaskName, Created user's name + surname, Employee's name surname, Custemer's name + surname etc..

Servicestck.Ormlite equivalent of .include

Given the following example POCOS:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
...
[Reference]
public List<Item> Items { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
....
}
Is there a way to select a set of Orders and include their related items? Akin to a .include() in Entity Framework.
In terms of Service Stack API, a multi-entity version of LoadSingleById() which does eagerly load referenced fields.

Resources