Entity framework 3 table join with one right join - c#

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 }

Related

Joining table to other table using either one of two columns

I'm currently writing a program in C# and I want to load friendships from the database based on the id passed as function parameter.
I got 2 tables (I only display the important columns).
Table 1: players
+----------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+---------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(15) | NO | | NULL | |
+----------------------+---------------------+------+-----+---------+----------------+
Table 2: messenger_friends
+-------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+-------+
| user_one_id | int(11) | NO | PRI | NULL | |
| user_two_id | int(11) | NO | PRI | NULL | |
+-------------+---------+------+-----+---------+-------+
The thing is, my idea was the following: in messenger_friends, save one line for a friendship. I know I can save 2 for one friendship but it would mean more storage as 500 friendships would become 1000 records. Now, in my application I have to JOIN messenger_friends to players. I got this function:
public async Task<IReadOnlyList<MessengerFriend>> GetFriends(int playerId)
In here, I need to get all records from messenger_friends where EITHER user_one_id OR user_two_id is playerId. Then in the same query, I want to join it to players. I know I can get the records this way:
SELECT * FROM messenger_friends WHERE user_one_id = {playerId} OR user_two_id = {playerId}
But I'm not sure how to join it to the players table as I need to join EITHER user_one_id OR user_two_id with players.id
SELECT *
FROM players p
JOIN messenger_friends f ON p.id in (f.user_one_id, f.user_two_id)
WHERE p.id = {playerId}
or
SELECT *
FROM players p
JOIN messenger_friends f ON p.id = f.user_one_id
OR P.id = f.user_two_id
WHERE p.id = {playerId}

Better way to insert data in table from other table with ADO.NET

I have two tables:
Table1 - MainTable
---------------------------------------
| MainTableID | CustomerName | BookID |
---------------------------------------
Table2 - BookTable
----------------------
| BookID | BookName |
----------------------
| 1 | physics |
----------------------
| 2 | Math |
----------------------
I want to get the result like this:
---------------------------------------
| MainTableID | CustomerName | BookID |
---------------------------------------
| 1 | Alex | Math |
---------------------------------------
I have list of BookNames in BookTable and I want to insert Data in MainTable. I am using ADO.NET entity data model in visual studio and I am doing this so:
BookTable correspondingBook=(from row in entities.BookTable
where rows.BookName == "Math"
select rows).First();
MainTable itemToAdd = new MainTable();
itemToAdd.CustomerName = "Alex";
itemToAdd.BookID = correspondingBook.BookID;
entities.MainTable.Add(itemToAdd);
entities.SaveChanges();
Is it good solution for this problem? if no, Which will be better?

Linq get rows by enum values

Here is my enum values defined
public enum authaccess
{ read=0,create=1,update=2,delete=4}
As a Access Table looks like as below.
|id | tablename |columnname|permitted|
|----|-----------|----------|---------|
|1 | cms |header |3 |
|2 | cms |footer |2 |
|3 | cms |content |7 |
read access is permitted for all content, while 3 is for(create + update), and 7 for all rights.
As I need (x) button enabled in div where loggedInUser has delete authority
Using Linq, I used
new DbContext().tbl_access.where(k=>k.permitted > authaccess.delete){divid.class.add('close')}
but could not find a way to get a list of contents that can be changed by user ie 3 or (authaccess.create + authaccess.update)
[Clarification on edit]
The resultant table should be
|id | tablename |columnname|permitted|
|----|-----------|----------|---------|
|1 | cms |header |3 |
|2 | cms |footer |2 |
Because (header and footer) include create+update level access which is less than or equal to 3.
Thanks in advance for any help.
It looks like your authaccess has values for bit masking. For your requested create + update, a possible way to write your Linq is:
new DbContext().tbl_access
.Where(k => (k.permitted & (int)authaccess.create) > 0) &&
(k.permitted & (int)authaccess.update) > 0))
Do you want something like that;
var authAccessFilter = (int)authaccess.create + (int)authaccess.update;
var records = new DbContext().tbl_access.Where(k => k.permitted <= authAccessFilter).ToList();

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

Inputing Value in sql after counting c#

I'm kind of new to this but I'll try to give as much detail as possible. This is my SQL table.
Customers
Customers_Id (PK) | First | Last | Address | Phone | Tech_Id (FK) |
-------------------+-------+-------+--------------+----------+--------------+
1 | Bob | Smith | 123 Fake St. | 3298492 | 1 |
2 | John | Man | 123 Noe St. | 2930482 | 1 |
3 | Tom | Lee | 123 Polk St. | 9308523 | 2 |
...
Tech
Tech_Id (PK) | First | Last | Phone | Customer_Count |
--------------+-------+-------+---------+----------------+
1 | Tim | Bo | 9384027 | |
2 | Andy | Wong | 9374927 | |
3 | Jack | Help | 2183847 | |
...
I'm trying to find the best way to count how many customer that each tech has either using SQL Query or C# coding. I was thinking of doing query with Count and then insert into the Customer_Count in Tech table.
I'm using visual studio 2012 and SQL is created locally in visual studio. Please help!
You can do it through SQL - using a GROUP BY clause to group the result by each tech. You can use the COUNT function to return the number of customers assigned to each tech. You can put this in an UPDATE statement to update the customer_count field in the tech table for each tech.
For example:
UPDATE t
SET t.customer_count = COUNT(c.customer_id)
FROM tech t
INNER JOIN customers c ON c.tech_id = t.tech_id
GROUP BY c.tech_id
Remove the Customer_Count column from the tech table. It's best not to make columns which duplicate available data unless there's a valid performance reason. If you want it displayed as such, then create a view:
SELECT t.tech_id,
t.first,
t.last,
t.phone,
(SELECT COUNT(c.customer_id)
FROM customers c
WHERE c.tech_id = t.tech_id) AS Customer_Count
FROM tech t
Now you can query it like a table, but you're not tasked with maintaining data which is always up to date through this view.
I prefre to using Sql ,but failed...Disappionted..
But I am sure that you can use Ado.net to do this job.
Here is C# demo code.
//query from db use C#
var allCus = new List<Customers>();
var gps = allCus.GroupBy(w => w.Tech_Id);
foreach(var gp in gps) {
var techId = gp.Key;
var cnt = gp.Count();
//update Tech set Customer_Count = cnt where Tech_Id = techId
}
Here is Sql version
update Tech set Customer_Count = (select IdAndCnt.cnt from (select Tech_Id,count (Tech_id) as cnt from Customers group by Tech_Id ) as IdAndCnt where Tech.Tech_Id = IdAndCnt.Tech_Id)
Holp it works.

Categories