Linq except return whole table - c#

I have a table of items using linq to entities, say:
ID | Name | Attb1 | Attb2
1 | Apple | Green | Juicy
2 | Orange | Orange | sweet
etc
I have another list with just ID's in it.
Using Linq I want to return all fields from the item table except where the ID is in the list. i.e. if my list just has '1' in it I want to return 2 | orange | orange | sweet

You could try something like this
var result = table.Where(x => !list.Contains(x.id));
where I have assumed that table holds all the rows of your table and list contains the ids that you want to exclude.

Related

Delete Multiple rows in several tables

I have 3 tables in an SQL database:
Animal Status
Animals
Cart
I want to be able to delete several items from the Animals and Animal Status tables based on the cart.
What's the same between all the tables is the AnimalID which is the primary key in all the tables and based on that I'm supposed to delete them. But at the same time I need to delete it for someone with a specific email.
Example is if I have someone with the email 123#gmail.com and this person has 2 animals in his cart 1 with the ID 123 and the other with the id 456
I need to delete these 2 specific animals from the other 2 tables.
I know how to do it for 1 table but not when I have several tables that depend on each other along with them depending on the specific email when there are also other emails and animals in the cart.
Here is how it works on the outside:
x= AnimalStatus.Delete(AdoptCart.GetAnimalId(Session["email"].ToString()).ToString());
if (x > 0)
{
x = Animal.Delete(AdoptCart.GetAnimalId(Session["email"].ToString()).ToString());
if (x > 0)
{
AdoptCart.RemoveAllbyEmail(Session["email"].ToString());
Here are all the deletion codes in the order they work:
Removes the AnimalStatus based on the animals ID:
static public int Delete(string id)
{
int rowsAffected;
string strSql = string.Format("delete from AnimalStatus where AnimalID='" + id + "'");
rowsAffected = (int)dataservice.ExecuteNonQuery(strSql);
return rowsAffected;
}
Removes an animal from the animal table based on the animal's ID:
static public int Delete(string id)
{
int rowsAffected;
string strSql = string.Format("delete from Animal where AnimalID='" + id + "'");
rowsAffected = (int)dataservice.ExecuteNonQuery(strSql);
return rowsAffected;
}
Removes all animals from the Cart Table:
static public int Remove(string AnimalID)
{
int rowsAffected;
string strSql = string.Format("delete from Cart where AnimalID='" + AnimalID + "'");
rowsAffected = (int)dataservice.ExecuteNonQuery(strSql);
return rowsAffected;
}
Issue with this code is that all of that only deletes 1 animal and I need several removed.
I have tried creating a statement like this, but I didn't manage to make it work.:
Delete Animal.*, AnimalStatus.*
FROM Animal INNER JOIN
AnimalStatus ON Animal.AnimalID = AnimalStatus.AnimalID INNER JOIN
Cart ON Animal.AnimalID = Cart.AnimalID
WHERE (Cart.UserEmail = N'Email')
Based on the example I gave in words the ones that are supposed to be deleted are the following marked in //removed.
Cart Table
| AnimalID | Email_Addr |
--------------------------------------
| 123 | 123#gmail.com | //removed
| 456 | 123#gmail.com | //removed
| 765 | jj#gmail.com |
| 343 | bb#gmail.com |
| 256 | cc#gmail.com |
Animal Status Table
| AnimalID | Vaccinated |
--------------------------------------
| 123 | Yes | //removed
| 456 | Yes | //removed
| 765 | No |
| 343 | No |
| 256 | No |
Animals Tables
| AnimalID | Age |
--------------------------------------
| 123 | 3 | //removed
| 456 | 4 | //removed
| 765 | 3 |
| 343 | 7 |
| 256 | 10|
Looking at your current work there are a few things you could do. You could rewrite your query logic like you're asking, but what I'm not seeing in your example is primary/foreign key relationships. So cascade won't work with how you currently have your tables set up. This is a good write up of cascade delete. Cascade Delete
So if you don't want to rewrite everything you really could just do all of this in your C# code. All you'd have to do is loop through the cart table and get all of the id's that have the e-mail "123#gmail.com" and call your three delete statements. You'd just need to write a method to grab the id's and call the delete methods until the id variable is empty.
It just depends where you want all of the logic to exist, in sql or in your C# code. If you're using Entity Framework, whether code first or database first, you have options to use LINQ Query syntax or extension methods. Just depends on preference really.

LINQ join tables with value if no match

I know that there are some examples but I could not apply them on my code. I am pretty new to Linq and SQL. I have two tables I want to join.
First Table:
--------------
| Id | Count |
--------------
| 1 | 10 |
--------------
| 2 | 4 |
--------------
Second Table:
--------------
| Id | Name |
--------------
| 1 | Tom |
--------------
| 2 | John |
--------------
| 3 | Nick |
--------------
| 4 | Max |
--------------
As you can see, the second table has more records than the first. My goal is to join them based on the Id. The problem is that after I have joined the tables it only displays the matching records, which is Id 1 and 2. Though I want to display every Id (from 1 to 4) and if there is no match in both tables, there should be a default value 0.
It should look like this:
----------------------
| Id | Name | Count |
----------------------
| 1 | Tom | 10 |
----------------------
| 2 | John | 4 |
----------------------
| 3 | Nick | 0 |
----------------------
| 4 | Max | 0 |
----------------------
So far I have got this code:
// first table
var listCount = entity.tblKundes.Where(x => x.Studio == 2)
.Select(x => new { x.Id, x.Name})
.GroupBy(x => x.Name).ToList();
// second table
var listBerater = entity.tblUsers.Where(x => x.Studio == 2)
.Select(x => new { x.Id, x.Name})
.ToList();
// This join should be edited so that it displays non matching records as well
var test = listCount.Join(
listBerater,
count => count.Key,
berater => berater.Id,
(count, berater) => new { listCount = count, listBerater = berater }
).ToList();
Edit:
var test2 = (from list in listCount
join berater in listBerater on list.Berater equals berater.Id into gj
from sublist in gj.DefaultIfEmpty()
select new { sublist.Id, sublist.Nachname, sublist.Vorname }).ToList();
There is a typical concept in every Structured Query Languages which is called "Left join". Left-Join means that you will have all rows of data from first table even there is no equivalent in the second one. "Inner-Join" is a little different and only looks for matched rows of data.
Here you can find enough and complete information about your issue.
Left Join

Entity framework 3 table join with one right join

I have 3 tables:
strings
-----------
- string_id
- fallback_text
translations
----------------------
- translation_id
- string_id
- locale_id
- text
locales
---------------------
- locale_id
I want to achieve a resultset like this:
string_id | locale_id | text
----------------------------
1 | en_US | bread
1 | es_ES | pan
1 | fr_FR | NULL
There is no translation for "bread" in french, but I want it in the results.
In SQL would be somethink like:
SELECT strings.string_id, locales.locale_id, translations.text
FROM strings
JOIN translations on strings.string_id = translations.string_id
RIGHT JOIN locales on translations.locale_id = locales.locale_id
This SELECT doesn't resolve my problem. What I want is to list every string who hasn't a translation in each locale existing in locales table. I think this isn't going to happen in a SELECT statement.
Imagine we have:
locales table:
|locale_id|
-----------
|en_US |
|es_ES |
strings table:
|string_id|fallback_text|
-------------------------
|1 |bread |
|2 |water |
translations table:
|translation_id|string_id|locale_id|translation
-----------------------------------------------
|1 |1 |en_US |bread
|2 |2 |es_ES |agua
I would like to achieve this resultset:
string_id | locale_id | text
----------------------------
1 | en_US | bread
1 | es_ES | NULL
2 | en_US | NULL
2 | es_ES | agua
Thanks in advance.
The easiest way to accomplish this is simply use a SQL view.
Create an SQL view with you select statement, then create an entity to match that view. This entity will have 3 properties string_id, locale_id, text. Make sure that this entity defines (string_id and locale_id) as primary key. If you are using code first your mappings would be something like:
ToTable("MyViewName");
HasKey(x => new { x.string_id, x.locale_id });
var query = from s in db.strings
from t in db.translation
where s.string_id == t.string_id
select new {s.stringid, t.locale_id, t.text }

How to join one row to every row in source table using LINQ

I have the following table (table A):
ID | Data |
1 | Data1 |
2 | Data2 |
3 | Data3 |
4 | Data4 |
I have table B that has 1 row:
DummyID | Dummy |
1 | Dummy1 |
I have to join table A with table B in the following way:
ID | Data |DummyID | Dummy |
1 | Data1 |1 | Dummy1 |
2 | Data2 |1 | Dummy1 |
3 | Data3 |1 | Dummy1 |
4 | Data4 |1 | Dummy1 |
Obviously I can't use any ID in the on clause.
from item in context.TableA
join dummy in context.TableB on ? = ?
select new
{
RowA=item,
Dummy=dummy
}
How could I do that with LINQ?
That's a cross join which you can get via Linq in the following way
from item in context.TableA
from dummy in context.TableB
select new
{
RowA=item,
Dummy=dummy
}
Or the following in method syntax
context.TableA.SelectMany(
item => context.TableB.Select(dummy => new { RowA = item, Dummy = dummy }));
Note that if TableB every has more than one row you'll end up with N times M rows where N is the number of rows in TableA and M is the number of rows in TableB.
No need to join at all.
from item in context.TableA
select new
{
RowA = item,
Dummy = context.TableB.FirstOrDefault()
}
Having said that, I'd have to question why you're doing this. The idea of LINQ is to get your relational data into an object-oriented form. Why not just retrieve the TableB information once and do whatever processing you need to do in-memory? It would reduce the size of the payload you're transferring from the database back to the application.
Why do you want to use join. You want to use each item in your old sequence to create a different item in your new sequence. In LINQ you would use Enumerable.Select for this:
var dummy = context.Dummy.FirstOrDefault();
var newSequence = context.TableA
.Select(itemInTableA =>
new
{
RowA = itemInTableA,
Dummy = dummy,
});

how to structure data that will be fed into dropdown boxes?

I have denormalized data:
+----+----------+------+--------+
| pk | name | type | animal |
+----+----------+------+--------+
| 1 | alex | car | cat |
| 2 | alex | bike | cat |
| 3 | liza | car | dog |
| 4 | danielle | bike | dog |
| 5 | danielle | bus | dog |
+----+----------+------+--------+
I would like to have 3 dropdown boxes.
name
type
animal
after the user chooses the option for the first, there should be a cascade effect for the other dropdowns.
example: if the user chooses danielle for the name, the only two options for type would be bike and bus and the only option for animal would be dog
How should I structure the SQL tables? Should I denormalize?
I'd say that your solution depends on how much data do you have in this table.
If this table is relatively small, you could load it into memory, fill comboboxes by distinct values and then filter data by chosen field.
If it large, you maybe should denormalize your table as #astander says, fill comboboxes with data from reference tables and then when value changes, select filters from SQL like:
declare #name_id int -- input parameter, fill it with id of chosen name
-- filter for type combo
select distinct type_id from main_table where name_id = #name_id
-- filter for animal combo
select distinct animal_id from main_table where name_id = #name_id

Categories