How to query a composite id key inside a list - c#

How can I query a composite key field in a multiple IN clause SQL?
My Subsidiary is a composite of a String and a Company
public class Company
{
public virtual String Id { get; set; }
}
public class Subsidiary
{
public virtual String Id { get; set; }
public virtual Company Company { get; set; }
}
public class Disponibility
{
public virtual String IdCompany { get; set; }
public virtual String IdSubsidiary { get; set; }
}
Currently stuck at this
var subsidiarys = session.Query<Subsidiary>().ToList();
var result = session.Query<Disponibility>().Where(x => subsidiarys.Contains(???) ).ToList();
The generated query needs to be
SELECT * FROM VW_DISPONIBILITY D
WHERE (D.COMPANY, D.SUBSIDIARY) IN (SELECT S.COMPANY, S.SUBSIDIARY FROM SUBSIDIARY S);

Not all databases support oracle multiple IN clause so the only way to do this is by concatenating multiples or.
var disjunctions = Restrictions.Disjunction();
foreach (var sub in subsidiarys)
{
disjunctions.Add(Restrictions.Where<Disponibility>(x => x.IdCompany == sub.Company.Id && x.IdSubsidiary == sub.Id));
}
var result = session.QueryOver<Disponibility>()
.Where(disjunctions)
.List<Disponibility>();
Generated SQL
SELECT
...
FROM
VW_DISPONIBILITY this_
WHERE
(
(
this_.COMPANY = :p0
and this_.SUBSIDIARY = :p1
)
or (
this_.COMPANY = :p2
and this_.SUBSIDIARY = :p3
)
...
);

Related

How can i use SQL inner join statement as query in LINQ

SELECT
Id,
No,
NetAmount,
PaidAmount,
NetAmount - PaidAmount AS AmountToBePayed
FROM
(
SELECT
m.Id,
m.No,
SUM(NetAmount) as NetAmount,
(
SELECT
COALESCE( SUM( PaidAmount ), 0 )
FROM
A_Account_Payable_Payment_Invoice
) as PaidAmount
FROM
A_Account_Payable_Invoice_M m
INNER JOIN A_Account_Payable_Invoice_Item d ON
m.Id = d.A_Account_Payable_Invoice
GROUP BY
m.Id,
m.No
) a
How can i use this query directly in LINQ C#
As you mentioned on comment section you don't want to translate SQL to LINQ, you just want to directly run this script.
To do so first you need to create class that will match with your Script like:
[DataContract()]
public class PaymentInvoiceResult
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int No { get; set; }
[DataMember]
public int NetAmount { get; set; }
[DataMember]
public int PaidAmount { get; set; }
[DataMember]
public int AmountToBePayed { get; set; }
}
Then you need to use SqlQuery as following:
List<PaymentInvoiceResult> paymentInvoiceResultList = db.Database.SqlQuery<PaymentInvoiceResult>("Your Script").ToList();
You can simply use:
var results = db.ExecuteQuery(typeof(DTO), "sql query ");
Your dto should have members:
Id,
No,
NetAmount,
PaidAmount,
NetAmount - PaidAmount AS AmountToBePayed

Linq to Entities - how to delete many records with inner join

I have two classes:
public class Address
{
[Key]
public int ID_Address { get; set; }
public string URL { get; set; }
and:
public class Category_Address
{
[Key]
public int ID_Category_Address { get; set; }
public int ID_Category { get; set; }
public virtual Category Category { get; set; }
public int ID_Address { get; set; }
public virtual Address Address { get; set; }
}
I want to select ID_Address from Address table where URL = "anytextIwrite" and delete every record in Category_Address having the same ID_Address that I selected. How can I do that ?
Now I wrote this with a few assumptions. Obviously you'll want to use your own database names and whatever group names you want for them, but this is a fairly simple LINQ statement and join, followed by a foreach that should do what you want.
var toDelete = from addr in addresses
join cate in category_addresses on addr.id_address equals cate.id_address
where addr.url = "anytextIwrite"
select cate;
foreach (var record in toDelete) {
db.category_addresses.DeleteOnSumbit(record);
}
If still active, then try smth like this:
using (var context = new YourDbModel())
{
var deletingAddresses = context.Category_Addresses
.Where(ca => ca.Address.URL == "anytextIwrite")
.Select(ca => ca.Address)
.ToArray();
foreach(var address in deletingAddresses)
{
context.Category_Addresses.Attach(address);
var entry = context.Entry(address);
entry.State = EntityState.Deleted;
}
context.SaveChanges();
}
It worked for me, so maybe you need the same.

Selecting Entity Using Linq query with join and including nested property

I'm battling to retrieve a single Model/Entity using EntityFramework and Linq.
I have a Business with Members, I'm trying to retrieve the users' business based on the BusinessMembers table/entity.
I have the following entities/models:
public partial class Business
{
public Business()
{
BusinessMembers = new HashSet<BusinessMember>();
}
public int ID { get; set; }
public int ID_BusinessStatus { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Phone { get; set; }
public virtual BusinessStatus BusinessStatus { get; set; }
public virtual ICollection<BusinessMember> BusinessMembers { get; set; }
}
and
public partial class BusinessStatus
{
public BusinessStatus()
{
Businesses = new HashSet<Business>();
}
public int ID { get; set; }
[Required]
[StringLength(3)]
public string Code { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual ICollection<Business> Businesses { get; set; }
}
I then have the following method to return a Single Business Instance:
public Business GetBusinessForUser(string userId)
{
using (var db = new MyContext(_connectionString))
{
var q =
from b in db.Businesses
join bm in db.BusinessMembers on b.ID equals bm.ID_Business
where bm.UserId == userId
select b;
return q.FirstOrDefault();
}
}
Problem I'm having is I want to 'Include' the BusinessStatus for that single Business entity and don't know how to do this.
I need to be able to do:
Business businessEntity = _dataServices.GetBusinessForUser(userId);
if (businessEntity.BusinessStatus.Code == "ACT")
{
// Whatever
}
First, add this to the list of usings
using System.Data.Entity;
Then you can use the .Include() method to load additional children in your query
public Business GetBusinessForUser(string userId)
{
using (var db = new MyContext(_connectionString))
{
var q =
(from b in db.Businesses
join bm in db.BusinessMembers on b.ID equals bm.ID_Business
where bm.UserId == userId
select b).Include(business => business.BusinessStatus);
return q.FirstOrDefault();
}
}
I would also avoid using the join method explicitly. If your model has correct relationships (e.g. foreign keys), you should be able to just do this:
var q = db.Businesses
.Where(b => b.BusinessMembers.Any(bm => bm.UserId == userId))
.Include(b => b.BusinessStatus);
return q.FirstOrDefault();
or even
var q = db.BusinessMembers
.Where(bm => bm.UserId == userId)
.Select(bm => bm.Business)
.Include(b => b.BusinessStatus);

Add data to a list insde a list where item in the prerent list

I would like to select a where statement that adds items to a list where only product codes match. I have it so it gets all of the products sold in the sale but I would like there were statement to get only products in this sale.
PS: This is really hard to explain
Model
public class userSales
{
public string Name { get; set; }
public string UserName { get; set; }
public int Sale_Id { get; set; }
public int CostumerID { get; set; }
public string Sale_Date { get; set; }
public string Paid { get; set; }
public Nullable<int> Sale_Cost { get; set; }
public string Discount_Code { get; set; }
public List<SaleProduct> saleProductsList { get; set; }
}
public class SaleProduct
{
public int SaleID { get; set; }
public string ProductCode { get; set; }
public int ProductCount { get; set; }
public string Image_Path { get; set; }
public string Shoot_Date { get; set; }
public string Shoot_Info { get; set; }
}
Linq statement where I'm having trouble:
var test = (from _ClientData in db.ClientDatas
join _salesInfo in db.Sales_Infoes
on _ClientData.CostumerID
equals _salesInfo.CostumerID
where _ClientData.UserName == _userName
select new userSales()
{
CostumerID = _ClientData.CostumerID,
Name = _ClientData.Name,
UserName = _ClientData.UserName,
Sale_Id = _salesInfo.Sale_Id, // This is the item i would like to use in my were statement
Sale_Date = _salesInfo.Sale_Date,
Sale_Cost = _salesInfo.Sale_Cost,
Discount_Code = _salesInfo.Discount_Code,
Paid = _salesInfo.Paid,
// Problem here
saleProductsList = db.SaleProducts.Where()
}).ToList();
Got to this based on the answer:
var reult = db.ClientDatas.Where(a => a.UserName == _userName)
.Join(db.Sales_Infoes,
a => a.CostumerID,
b => b.CostumerID,
(a, b) => new userSales()
{
CostumerID = a.CostumerID,
Discount_Code = b.Discount_Code,
Sale_Cost = b.Sale_Cost,
Sale_Id= b.Sale_Id,
Name = a.Name,
Sale_Date = b.Sale_Date,
UserName = a.UserName,
Paid = b.Paid,
saleProductsList = db.SaleProducts.Where(c => c.SaleID == b.Sale_Id).ToList()
}).ToList();
You're not looking for a where, you're looking for a join. Where filters the results on a single table, join intersects two tables which is actually what you want here.
var result = db.Sales_Infoes.Where(x => x.UserName == _userName)
.Join(db.ClientDatas,
x => x.Sale_Id,
y => y.Sale_id,
(x, y) => new userSales() {
// x is SalesInfo obj y is ClientDatas obj do assignement here
Name = y.Name,
Sale_Date = y.Sale_date
}).ToList();
Just fyi I haven't had a chance to test that but it's the basic idea. You don't need a select like in your statement because the last argument I'm passing into join is the lambda (x, y) => ... in that case x and y are the current row from each table (that we've gotten from applying our where to the user sales table then joining those results into the salesproduct table) so whatever projections you want to do occur there. The other two method args above that are the telling join which fields to compare, it's the 'key selector' lambda expression for each table.

OrmLite Selecting Multiple Columns Across Joined Tables

I'm having some difficulty populating some columns in a POCO using OrmLite. I have three tables named Dog, Bowl and DogBowl. DogBowl is a junction table and holds the id of Dog and Bowl.
Dogs
PK Id: int, not null
Breed: varchar(20), not null
Name: varchar(20), not null
Bowls
PK Id: int, not null
Type: varchar(20), not null
Color: varchar(20), not null
Dogs_Bowls
PK: DogId, not null
PK: BowlId, not null
Here are the POCOs I have mapped
public class Dog : IHasId<int>
{
[AutoIncrement]
public int Id { get; set; }
[Required]
public string Breed { get; set; }
[Required]
public string Name { get; set; }
}
public class Bowl : IHasId<int>
{
[AutoIncrement]
public int Id { get; set; }
[Required]
public string Type { get; set; }
[Required]
public string Color { get; set; }
}
public class DogBowl
{
[Required]
public int DogId { get; set; }
[Required]
public int BowlId { get; set; }
[Ignore]
public string DogName { get;set; }
[Ignore]
public string BowlColor { get;set; }
}
This is the c# code I'm running.
var dogBowl = db.Select<DogBowl>(db
.From<Dog>()
.Join<Dog, DogBowl>((d, db) => d.Id == db.DogId)
.Join<DogBowl, Bowl>((db, b) => db.BowlId == b.Id)
.Where<Dog>(d => d.Id == 5))
.ToList();
The SQL I would like to produce is this:
select
db.DogId,
db.BowlId,
d.Name AS DogName,
b.Color as BowlColor
from DogBowl db
join dog d on db.DogId = d.Id
join bowl b on db.BowlId = b.Id
where d.Id = 5
My problem is that the DogBowl.DogName and DogBowl.BowlColor properties are null after the code executes. I'm using the instructions provided on https://github.com/ServiceStack/ServiceStack.OrmLite from the section entitled "Selecting multiple columns across joined tables" but it's not working. How can I get the DogBowl.DogName and DogBowl.BowlColor properties populated?
The SQL generated may be correct. You can verify the generated SQL after execution by checking the property db.GetLastSql().
The problem is that by assigning the result as
db.Select<DogBowl>
, you are creating a List of DogBowl objects. The DogBowl properties DogName and BowlColor would always be null because there is no field in the SQL statement which matches those names exactly. OrmLite will not magically figure out what goes there - you have to have them match by name.
If you want to assign the result to a "flat" object with fields from Dog and Bowl, you could define a new DTO and assign the result, like so:
public class FullDogBowl
{
public int DogId { get; set; }
public int BowlId { get; set; }
public string Breed { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Color { get; set; }
}
var dogBowl = db.Select<FullDogBowl>(db
.From<Dog>()
.Join<Dog, DogBowl>((d, db) => d.Id == db.DogId)
.Join<DogBowl, Bowl>((db, b) => db.BowlId == b.Id)
.Where<Dog>(d => d.Id == 5))
.ToList();
Alternatively, if you know exactly the SQL you want to use, just use it:
string sql = #"select
db.DogId,
db.BowlId,
d.Name AS DogName,
b.Color as BowlColor
from DogBowl db
join dog d on db.DogId = d.Id
join bowl b on db.BowlId = b.Id
where d.Id = #dog_id ";
var dogBowlList = db.SqlList<DogBowl>(sql, new { dog_id = 5, });
Wanted to add to Raul's answer that [Ignore] tells OrmLite to ignore the property completely so your approach of re-using a table as the merged POCO "view" wont work. I recommend instead splitting the resultset POCO out into a separate POCO with all the fields you want returned:
public class DogBowl
{
[Required]
public int DogId { get; set; }
[Required]
public int BowlId { get; set; }
}
public class DogBowlInfo
{
public int DogId { get; set; }
public int BowlId { get; set; }
public string DogName { get; set; }
public string BowlColor { get; set; }
}
Which now returns a populated resultset with:
using (var db = OpenDbConnection())
{
db.DropAndCreateTable<Dog>();
db.DropAndCreateTable<Bowl>();
db.DropAndCreateTable<DogBowl>();
var dog = new Dog { Breed = "Breed", Name = "Name" };
var bowl = new Bowl { Color = "Color", Type = "Type" };
db.Save(dog);
db.Save(bowl);
db.Insert(new DogBowl { DogId = dog.Id, BowlId = bowl.Id });
var dogBowl = db.Select<DogBowlInfo>(
db.From<Dog>()
.Join<Dog, DogBowl>((d, b) => d.Id == b.DogId)
.Join<DogBowl, Bowl>((d, b) => d.BowlId == b.Id)
.Where<Dog>(d => d.Id == dog.Id));
dogBowl.PrintDump();
}

Categories

Resources