ASP.net JSON Rest API Output from Complex Class from Database - c#

Database Tables
tbl_Product
- id (pk)
- name
- price
tbl_image
- id (pk)
- prd_id (fk)
- imageUrl
I want to the Json result from my database like this
[
{
"id":"",
"name":"",
"price":"",
"images":[
{
"id":"",
"imageUrl":""
},
{
"id":"",
"imageUrl":""
},
{
"id":"",
"imageUrl":""
}
]
},
{
"id":"",
"name":"",
"price":"",
"images":[
{
"id":"",
"imageUrl":""
},
{
"id":"",
"imageUrl":""
}
]
}
]
C# Object Class
class ProductModel
{
public int id {get; set;}
public string name {get; set;}
public string price {get; set;}
public ImageModel images {get; set;}
}
class ImageModel
{
public int id {get; set;}
public int prd_id {get; set;}
public string imageUrl {get; set;}
}
First of all i would like to thank you for reading my simple question.
How to get json output like above ..
I am confused if i join the query to get the output like this ..
select * from tbl_Product a inner join tbl_images b on a.id = b.prd_id
This will result join the two tables, How do i separate it out from Business logic to generate that output ..
or
Do we need to GetAllProduct from tbl_Product table and do for loop and while mapping datatable to object fetch imageByProductId and add to that ProductModel Object ..
I am not sure is this the fastest way .. i don;t want to use entity framework ...
I want just a method which provide me JSON in above format and try to make sure the method is in C# without any framework
Thank you for reading my question and waiting for your ans.

First of all your models need to be like this
class ProductModel
{
public int id {get; set;}
public string name {get; set;}
public string price {get; set;}
public IList<ImageModel> images {get; set;}
}
class ImageModel
{
public int id {get; set;}
public string imageUrl {get; set;}
}
and then try below linq to sql query
tbl_Product.Select(prod =>
new ProductModel
{
id = prod.id,
name = prod.name,
price = prod.price,
images = prod.tbl_image.Select(img => new ImageModel
{
id = img.id,
imageUrl = img.imageUrl
})
}).ToList()

If you are working with Azure SQL Database or you can install SQL Server 2016 then you can add FOR JSON AUTO clause:
select * from tbl_Product a inner join tbl_images b on a.id = b.prd_id
FOR JSON AUTO
This would return you JSON text that you can simply return as response of API.

Related

Get prev, current, next on MongoDB c#

I have a Collection Students which Stores registered students data in MongoDB. It has StudentName, SaveDate etc. fields. I am displaying the details to my website from my .net framework WebAPI.
What I want to do is Get StudentDetails with prev next student ID's by the order of SaveDate.
My current query gets Student details by student id from below query,
var collection = StudentDB.Collection<Student>("StudyMaterials");
var curfilter = Builders<Student>.Filter.Eq(x => x.studentID, studentID);
studentDetails= collection.Find(curfilter).FirstOrDefault();
This is my Student.cs class,
public class Student
{
[BsonRepresentation(BsonType.String)]
public Guid StudentID {get; set;}
public string StudentName {get; set;}
[BsonRepresentation(BsonType.String)]
public Guid NextStudentID {get; set;}
[BsonRepresentation(BsonType.String)]
public Guid PrevStudentID {get; set;}
}
I want to use aggregation but don't know how to sort by multiple sort definitions on the aggregation framework.
First of all, I don't think you need to keep the students like that. I suggest the following:
public class Student
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public DateTime SaveDate { get; set; }
}
You need to make sure that the documents are sorted by SaveDate. For instance, when inserting new students into the database you can do it like this:
var student = new Student
{
Name = "Sara",
SaveDate = DateTime.UtcNow
};
context.Students.InsertOne(student);
Now, you can get the documents with Skip and Limit:
var skip = 0;
var limit = 1;
var context = new MongoContext();
var filter = Builders<Student>.Filter.Empty;
var result = context.Students.Find(filter).Skip(skip).Limit(limit).FirstOrDefault();
Increment skip to get next and so on.

How to only return a list of inherited instances if defined, otherwise return the base class

I am trying to extend an existing application. I need to implement the ability to define multiple instances of a product while keeping it backward compatible with the existing implementation of the product class.
Current Product class:
public class Product {
public int Id {get; set;}
public string Name {get; set;}
public decimal Price {get; set;}
}
Getting a list is done by a simple EF call context.Products.ToList().
Now I want to extend the existing class to be able to define "subproducts". My first try:
public class Product {
public int Id {get; set;}
public string Name {get; set;}
public decimal Price {get; set;}
public List<SubProduct> SubProducts {get; set;}
}
public class SubProduct : Product {
public string Identifier {get; set;}
}
Now, If I have Product instance ProductA (€5, with no subproducts) and instance ProductB (€7) with 2 Subproducts "1" and "2", I need to get the following list when fetching all products:
Name Price
ProductA €5
ProductB-1 €7
ProductB-2 €7
How can I fetch a list of all products, but returning a mix of subproducts (without their ancestor) and products?
This has to be returned in a way that this list is compatible with all already existing calls within the application (so that the simple EF call as above would get this list)
It seems you need SelectMany:
var resss = produc
.SelectMany(p => p.SubProducts ?? new List<SubProduct>() { new SubProduct { Identifier = "" } },
(parent, child) => new { Name = !string.IsNullOrWhiteSpace(child.Identifier) ? parent.Name + "-" + child.Identifier : parent.Name, parent.Price});
The Result is:
In order to be backwards compatible you need HasDiscriminator in order to know which row is what entity

How to join multiple collections using Mongodb C# driver

I need to join 3 collections in aggregation with multiple $lookup
I tried in C# driver it allow me to $lookup User collection but can't perform second $lookup for Setting collection.
Anyone can help?
db.Transactions.aggregate([
{
$lookup:
{
from: "Account",
localField: "AccountId",
foreignField: "_id",
as: "Account"
}
},
{
$lookup:
{
from: "User",
localField: "UserId",
foreignField: "_id",
as: "User"
}
}
])
.match({
})
.project({})
here is the C# code:
var account = _dbClient.GetDatabase(_dbName).GetCollection<Account>("Accounts");
var user = _dbClient.GetDatabase(_dbName).GetCollection<User>("Users");
var transaction = _dbClient.GetDatabase(_dbName).GetCollection<Transaction>("Transactions");
var result = (from t in transaction.AsQueryable()
join a in account.AsQueryable() on t.AccountId equals a.Id
join u in user.AsQueryable() on t.UserId equals u.Id into userList
from acc in userList.DefaultIfEmpty()
where acc.CompanyName.ToLower().Contains(companyName) && c.CreatedDate >= fromDate && c.CreatedDate <= toDate
select new TransactionHistory
{
Id = t.Id,
CompanyName = acc.CompanyName,
UserId = u.UserId
FirstName = u.FirstName
}).ToList();
I got the error $project or $group does not support {document}. using Linq.
I need to join 3 collections in aggregation with multiple $lookup
Given the following classes:
public class Transactions
{
public ObjectId Id { get; set; }
public int UserId { get; set; }
public int AccountId { get; set; }
public int SettingId { get; set; }
}
public class Account
{
public int Id {get; set;}
public int Name {get; set;}
}
public class User
{
public int Id {get; set;}
public int Name {get; set;}
}
public class Setting
{
public int Id {get; set;}
public int Name {get; set;}
}
You can perform multiple $lookup stage as below using MongoDB .NET/C# driver (currently v2.9):
var collection = database.GetCollection<Transactions>("transactions");
var docs = collection.Aggregate()
.Lookup("account", "AccountId", "_id", "asAccounts")
.Lookup("user", "UserId", "_id", "asUsers")
.Lookup("setting", "SettingId", "_id", "asSettings")
.As<BsonDocument>()
.ToList();
foreach (var doc in docs) {
Console.WriteLine(doc.ToJson());
}
You can add a Match, in between/before/after if you would like to filter for specific values. Just keep in mind that the documents after altered after each Lookup stage.
Worth mentioning that if you need to join multiple collections as part of your common operations, you should reconsider the database data model. Please see Schema Design: Summary for more information.

C# Mongodb: How to find in nested list of documents and select one field

I have the following models:
public class Car
{
public string Id {get; set;}
public IList<Driver> Drivers {get; set;}
}
public Driver
{
public string Id {get; set;}
public string IsActive {get; set;}
{
I want to find a car by id and select driver's id that is active. So
var carId = "123";
carCollection.Find(c=>c.Id == carId)
How to add selection for active driver's id?
PS. Only one active driver could be.
using mongo driver this can be done like below
var query = Query.And(Query.EQ("Id", carId),
Query.EQ("Drivers.IsActive",
"true"));
MongoCursor<Car> cursor = carCollection.FindAs<Car>(query);
if (cursor.Count() > 0 && cursor.ToList()[0].Drivers != null)
{
// use the cursor.ToList()[0].Drivers
}

Get details from 2 tables asp.net web api

I'm creating a web api. I have two tables
Employee_details
SlNo Employeeid R_ID
1 2022 AC1
2 2023 AC2
Id_details
SlNo R_ID L_ID
1 AC1 L001
2 AC1 L002
3 AC1 L003
4 AC2 L004
5 AC2 L005
I created a web api with RESTful services. I need to get all the L_ID of a particular Employeeid. For example if I request for employeeid 2022 I should get L001 L002 and L003. Help me please. I created the tables using code first and enabling migration
Code
Model class
Employee_details.cs
public class Employee_details
{
public int slNo {get; set;}
public string Employeeid {get; set;}
public string R_ID {get; set;}
//Navigation
public Id_details Id_details{get; set;}
}
Id_details.cs
public class Id_details
{
public int slNo {get; set;}
public string R_ID {get; set;}
public string L_ID {get; set;}
}
Controller
public IQueryable<Employee_id> Getdetails(string employeeid )
{
return db.Employee_details
.Where(b => b.Employeeid.Equals(employeeid, StringComparison.OrdinalIgnoreCase)).Include(c => c.Id_details);
}
I did not make foreign key reference since R_ID field in Table 2 is not a primary key.
If you use Native SQL this query is your return data.
SELECT ID.L_ID
FROM Id_details AS ID
INNER JOIN Employee_details ED
ON ID.R_ID = ED.R_ID
WHERE ED.Employeeid = '2022'
or if you use EntitiyFramework
this query return equels R_ID records then set Employee_details condition
var res = db.Id_details.Join(db.Employee_details, x => x.R_ID , y => y.R_ID , (x, y) => x).ToList();
or you can select any R_ID in containsList
var conditionList =db.Employee_details.where(p=>p.Employeeid.equals('2022')).select(p=>p.R_ID);
then set condition using conditionList search
db.Id_details.where(p=> conditionList.contains(p.R_ID)).select ( ... );

Categories