Inserting data using Linq to SQL with foreign keys - c#

I have a database that contains 'Personne' table, 'Patient' table (this one contains a foreign key to the id of 'Personne'), and 'RendezVous' table. i want to add a new element on my RendezVous table, but in my 'RendezVous' table i want the idPatient, and i am entering the first and last name in my app so i have to do a search on 'Personne' table to get the idPerson, and search that id on my 'Patient' table to get it the idPatient. If the patient doesn't exist, i put the id on 1. I'm using LinQ to SQL, but it doesn't work... Can i get some help?
public void AddRdv(DateTime date, byte idMedecin, string nomPatient, string prenomPatient, bool important, string notes)
{
string con = $#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}\MCDatabase.mdf;Integrated Security=True";
MCDataClassDataContext dataClass = new MCDataClassDataContext(con);
var patientRdv = (from personne in dataClass.Personne
where nomPatient == personne.nom && prenomPatient == personne.prenom
join patient in dataClass.Patient on personne.Id equals patient.IdPersonne
select personne);
Personne pers=patientRdv.First();
if (patientRdv.Count()!=0)
{
pers = patientRdv.First();
RendezVous rdv = new RendezVous
{
Date = date,
IdPatient = pers.Id,
IdMedecin = idMedecin,
Important = important,
Fait = false,
Note = notes
};
dataClass.RendezVous.InsertOnSubmit(rdv);
dataClass.SubmitChanges();
}
else
{
RendezVous rdv = new RendezVous
{
Date = date,
IdPatient = 1,
IdMedecin = idMedecin,
Important = important,
Fait = false,
Note = notes
};
dataClass.RendezVous.InsertOnSubmit(rdv);
dataClass.SubmitChanges();
}
}

Related

How to add condition to GroupJoin (or use multiple keys)?

I've got database table that stores system logs. This table has columns SourceContext and ObjectId. SourceContext stores information in what context should I interpret this log. So if SourceContext equals "Product", that means that this particular log in about "Product". Then, ObjectId is exact id of that object (e.g. id of "Product").
I needed to display logs to my customer. But instead of ObjectId I needed to display real object name from other table in database. This is what I've managed to create:
var query = from l in db.Logs
join c in db.Client on new { Key1 = l.SourceContext, Key2 = l.ObjectId } equals new { Key1 = "Client", Key2 = (int?)c.id } into c_result
from c_r in c_result.DefaultIfEmpty()
join p in db.Product on new { Key1 = l.SourceContext, Key2 = l.ObjectId } equals new { Key1 = "Product", Key2 = (int?)p.id } into p_result
from p_r in p_result.DefaultIfEmpty()
join w in db.Warehouse on new { Key1 = l.SourceContext, Key2 = l.ObjectId } equals new { Key1 = "Warehouse", Key2 = (int?)w.id } into w_result
from w_r in w_result.DefaultIfEmpty()
join i in db.Invoice on new { Key1 = l.SourceContext, Key2 = l.ObjectId } equals new { Key1 = "Invoice", Key2 = (int?)i.id } into i_result
from i_r in i_result.DefaultIfEmpty()
select new LogsViewModel { Log = l, Name = c_r.name + "" + p_r.name + "" + w_r.name + "" + i_r.invoice_number, UserName = null };
It works fine, but now I need to conditionally disable some of those joins (optimalization reasons, not all contexts requre to load object names from some tables). So I decided to convert Linq query syntaxt to method syntax.
Here is what I want to accomplish:
public static IQueryable<LogsViewModel> GetLogs(ApplicationDbContext db)
{
var query = from l in db.Logs
select new LogsViewModel { Log = l, Name = "", UserName = null };
// lines below will be split in switch/case block in the future, to conditionally disable them
query = GetUserNames(db, query);
query = GetInvoiceNames(db, query);
query = GetWarehouseNames(db, query);
// etc...
return query;
}
So I want to split my query into methods. Typical method would look like:
public static IQueryable<LogsViewModel> GetInvoiceNames(ApplicationDbContext db, IQueryable<LogsViewModel> query)
{
return query.GroupJoin(db.Invoice.DefaultIfEmpty(), logsVM => logsVM.Log.ObjectId, invoice => invoice.id, (logsVM, invoice) => new LogsViewModel
{
Log = logsVM.Log,
Name = logsVM.Name + "" + invoice.FirstOrDefault().invoice_number,
UserName = logsVM.UserName
});
}
The problem with GetInvoiceNames method is that it joins all logs with "Invoice" table, no matter SourceContext equals "Invoice" or not. I can't use Where clause or SelectMany because it would affect other logs. So in other words: I need to add a condition to GroupJoin so it will join all logs where SourceContext equals some specific value. Do you have any ideas how to solve it?

crateDB read 10k rows without iteration in Npgsql C# client

I have 10k row data in crate database. How to read the data without iteration. I am using crateDB C# Npgsql client for my service.
var connString = "Host=myserver;Username=mylogin;Password=mypass;Database=mydatabase";
await using var conn = new NpgsqlConnection(connString);
await conn.OpenAsync();
// Retrieve all rows
var cmd = new NpgsqlCommand("select * from sensordata where timestamp >= extract(epoch from (now() - interval '1 week'))", conn);
var result = new List<SensorDataViewModel>();
using (var reader = cmd.ExecuteReader())
{
while(reader.HasRows && reader.Read())
{
SensorDataViewModel item = new SensorDataViewModel {
sensorid = reader["sensorid"].ToString(),
deviceid = reader["deviceid"].ToString(),
reading = Convert.ToInt32(reader["reading"]),
timestamp = (double)reader["timestamp"]
};
result.Add(item);
}
}
here im reading each row at a time in while loop. that take lot of time in processing ?
Maybe you need to consider using EntityFrameworkCore. For more details please refer to https://www.npgsql.org/efcore/index.html
Below is my sample code which I have tried. In the CrateDb contain 2 tables. One is customers and another is todo. These table has a relationship where customer.id=todo.customer_id.
The first and second query inside the sample is just select every records from the 2 tables respectively.
The third query is using join to retrieve related records according to the relationship and filtered by customers.id.
class Program
{
static async Task Main(string[] args)
{
MemoContext memoContext = new MemoContext();
//select * from customers
List<Customer> customers = memoContext.customers.Select(x => new Customer
{
id = x.id,
name = x.name,
contactno = x.contactno,
email = x.email
}).ToList();
//select * from todo
List<Todo> todos = memoContext.todo.Select(x => new Todo
{
complete = x.complete,
customer_id = x.customer_id,
id = x.id,
title = x.title
}).ToList();
//SELECT c.name, c.email, c.contactno, t.title, t.complete
//FROM customers AS c
//JOIN todo AS t ON t.customer_id = c.id
//WHERE c.id=1
var memo = memoContext.customers.Join(
memoContext.todo,
c => c.id,
t => t.customer_id,
(c, t) => new
{
id = c.id,
name = c.name,
email = c.email,
contactno = c.contactno,
todotitle = t.title,
complete = t.complete
}).Where(n => n.id == 1).ToList();
}
}
class MemoContext : DbContext
{
public DbSet<Customer> customers { get; set; }
public DbSet<Todo> todo { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("Host=localhost;Port=5432;Username=crate;SSL Mode=Prefer;Database=doc");
}
I hope it is useful to you.

How to pass or copy table field value from one table to another table using ASP.NET MVC and SQL Server

I have two tables named Order and Invoice_Line_Items. I have a column called "invoice_number" in both tables "invoice_number" and Invoice_Line_Items. But "invoice_number" column in Invoice_Line_Items table is empty. I need to copy the data present in the "invoice_number" column from the Order table to "invoice_number" column in Invoice_Line_Items table.
This is an example of what I want to achieve
Looks like the relationship between these 2 tables are Order_id?
This is just the example:
var query = from it in db.Invoice_Line_Items
join order in db.Order
on it.Order_id equals order.Order_id into lg
from order in lg.DefaultIfEmpty()
select new Invoice_Line_Items
{
Order_id = it.Order_id,
Invoice_number = order == null? null: order.Invoice_number,
item = it.item,
quantity = it.quantity
};
I managed to solve the issue and here is the code below
changed the table name from order to ordering
the invoice_number from Invoice_Line_Items made it retrieve the maximum number from ordering table order_id
public ActionResult SaveOrder(Order[] requesting)
{
string result = "Error! Order Is Not Complete!";
using (mymodel dbb = new mymodel())
{
var customerId = Guid.NewGuid();
Ordering ord = new Ordering();
ord.CustomerId = customerId;
ord.date_order_placed = DateTime.Now;
dbb.Orderings.Add(ord);
if (dbb.SaveChanges() > 0)
{
string order_id = dbb.Orderings.Max(o => o.invoice_number);
foreach(var item in requesting)
{
Invoice_Line_Items in_l_i = new Invoice_Line_Items();
in_l_i.invoice_number = order_id;
in_l_i.department = item.depart;
in_l_i.service = item.Service;
in_l_i.gender = item.Gender;
in_l_i.item = item.Item;
in_l_i.quantity = item.Quantity;
in_l_i.price = item.price;
dbb.Invoice_Line_Items.Add(in_l_i);
}
if (dbb.SaveChanges() > 0)
{
result = "Success! Order Is Complete!";
}
}
}
return Json(result, JsonRequestBehavior.AllowGet);
}

SQL Exception violation of primary key constraint when updating data

private void FormRentBook_Load(object sender, EventArgs e)
{
librarydb sorgu = new library();
var book = from booklist in query.k_Books
join isrent in query.k_Bookstatus
on booklist.Book_statusId equals isrent.k_typeid
join booktype in query.k_BookType
on booklist.book_type equals booktype.ID
select new
{
booklist.Book_Name,
booklist.Book_Author,
booktype.Book_type,
booklist.Book_Page,
booklist.ID,
isrent.k_typecomment,
};
bookscreen.DataSource = book.ToList();
bookscreen.Columns[0].HeaderText = "Book Name";
bookscreen.Columns[1].HeaderText = "bookscreen Author";
bookscreen.Columns[2].HeaderText = "Book Type";
bookscreen.Columns[3].HeaderText = "Page Number";
bookscreen.Columns[4].Visible = false;
bookscreen.Columns[5].HeaderText = "Book Status";
bookscreen.Show();
label6.Text = DateTime.Now.ToString();
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
}
public int a;
private void bookscreen_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
label1.Text = bookscreen.CurrentRow.Cells[0].Value.ToString();
label2.Text = bookscreen.CurrentRow.Cells[1].Value.ToString();
a =int.Parse( bookscreen.CurrentRow.Cells[4].Value.ToString());
label3.Text = bookscreen.CurrentRow.Cells[5].Value.ToString();
}
k_Rentedbooks rent = new k_Rentedbooks();
rent.renter_id = Login.k_id;
rent.renter_id = int.Parse(bookscreen.CurrentRow.Cells[4].Value.ToString());
rent.rent_date = DateTime.Now;
DateTime return = DateTime.Now;
int day;
day = Convert.ToInt32(comboBox1.SelectedItem.ToString());
rent.returndate = return.AddDays(day);
db.k_Rentedbooks.Add(rent);
var updatebook = db.k_Books.Where(w => w.ID ==a).FirstOrDefault();
updatebook.Kitap_statusId = 2;
db.SaveChanges();
i need to add data to k_KiralananKitaplar and update a row named Kitap_DurumId = 2 but i can only add data or update i cant do in one time db.SaveChanges give me error
Here's a sample of the data:
Kitap_Adi = book name,
Kitap_Yazar = book_author,
Kitap_Tur = book type,
Kitap_Sayfa = book page,
Kitap_DurumId = book status
The error message is
SqlException: Violation of PRIMARY KEY constraint 'PK_k_KiralananKitaplar'. Cannot insert duplicate key in object 'dbo.k_KiralananKitaplar'. The duplicate key value is (0).
In your update statement:
var updatebook = db.k_Books.Where(w => w.ID ==a).FirstOrDefault();
updatebook.Kitap_statusId = 2;
db.SaveChanges();
You're selecting a record where Id == a using FirstOrDefault and given that EntityFramework can't update this record, I'm going to assume that no record exists where Id == a so you need to handle a null return value from your query:
var updatebook = db.k_Books.FirstOrDefault(w => w.ID == a);
if (updatebook != null)
{
updatebook.Kitap_statusId = 2;
db.SaveChanges();
}
In this case, if a record was returned by the query, it'll update Kitap_statusId, otherwise, it won't do anything.
Update
Per OP comment on this question:
i solved problem but now i need to find when i insert new data in a table other table insert to same table to how can i do that
You just need to get the Id values of the newly insert entity and use that to insert a record into the 2nd table.
So in your code you have the first item being inserted:
db.k_Rentedbooks.Add(rent);
When you do the SaveChanges() for this, it'll automatically update the entity with its new Id, so lower down in that function you can then add a new record to the 2nd table using the Id value for rent.
As a rough example:
var Book = new Book{ statusId = rent.Id };
db.SecondTable.Add(Book);
db.SaveChanges();

Linq to Entity Left Outer Join

I have an Entity model with Invoices, AffiliateCommissions and AffiliateCommissionPayments.
Invoice to AffiliateCommission is a one to many, AffiliateCommission to AffiliateCommissionPayment is also a one to many
I am trying to make a query that will return All Invoices that HAVE a commission but not necessarily have a related commissionPayment. I want to show the invoices with commissions whether they have a commission payment or not.
Query looks something like:
using (var context = new MyEntitities())
{
var invoices = from i in context.Invoices
from ac in i.AffiliateCommissions
join acp in context.AffiliateCommissionPayments on ac.affiliateCommissionID equals acp.AffiliateCommission.affiliateCommissionID
where ac.Affiliate.affiliateID == affiliateID
select new
{
companyName = i.User.companyName,
userName = i.User.fullName,
email = i.User.emailAddress,
invoiceEndDate = i.invoicedUntilDate,
invoiceNumber = i.invoiceNumber,
invoiceAmount = i.netAmount,
commissionAmount = ac.amount,
datePaid = acp.paymentDate,
checkNumber = acp.checkNumber
};
return invoices.ToList();
}
This query above only returns items with an AffiliateCommissionPayment.
I'm not sure if EF supports this (nor am I sure if you are using EF2 or EF4), but this is the solution in Linq2Sql so it might be worth trying:
using (var context = new MyEntitities())
{
var invoices = from i in context.Invoices
from ac in i.AffiliateCommissions
join acp in context.AffiliateCommissionPayments on ac.affiliateCommissionID equals acp.AffiliateCommission.affiliateCommissionID into acp_join
from acp_join_default in acpg.DefaultIfEmpty()
where ac.Affiliate.affiliateID == affiliateID
select new
{
companyName = i.User.companyName,
userName = i.User.fullName,
email = i.User.emailAddress,
invoiceEndDate = i.invoicedUntilDate,
invoiceNumber = i.invoiceNumber,
invoiceAmount = i.netAmount,
commissionAmount = ac.amount,
datePaid = acp.paymentDate,
checkNumber = acp.checkNumber
};
return invoices.ToList();
}
The main change here is the into acpg after your join, and the DefaultIfEmpty line.
It's almost always a mistake to use join in LINQ to SQL and LINQ to Entities.
Guessing that the association from AffiliateCommission to AffiliateCommissionPayment is called Payment, you can just do:
using (var context = new MyEntitities())
{
var invoices = from i in context.Invoices
from ac in i.AffiliateCommissions
where ac.Affiliate.affiliateID == affiliateID
select new
{
companyName = i.User.companyName,
userName = i.User.fullName,
email = i.User.emailAddress,
invoiceEndDate = i.invoicedUntilDate,
invoiceNumber = i.invoiceNumber,
invoiceAmount = i.netAmount,
commissionAmount = ac.amount,
datePaid = (DateTime?) ac.Payment.paymentDate,
checkNumber = (int?) ac.Payment.checkNumber
};
return invoices.ToList();
}
LINQ to SQL and LINQ to Entities will both coalesce nulls. The casts are necessary because the inferred type will be based on the type of AffiliateCommissionPayment.paymentDate, which might not be nullable. If it is, you don't need the cast.

Categories