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

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

Related

Using Parent and Child FK in Entity Framework

There are some situations using Foreign Key in a table that FK has Parent or Child relations with another table as shown below:
Staff:
Id | Name | CityId |
-------------------------
1001 | John | 1 |
1002 | Mary | 2 |
1003 | Bill | 3 |
1004 | Jose | 4 |
1005 | Anna | 5 |
City:
Id | Name | CountryId |
----------------------------
1 | NY | 101 |
2 | Paris | 102 |
3 | London | 103 |
4 | Rome | 104 |
5 | Tokyo | 105 |
Country:
Id | Name |
---------------
101 | USA |
102 | France |
103 | UK |
104 | Italy |
105 | Japan |
My question is that: Should we use only CityId as FK in the Staff entity, or is it better to include CityId and its parent CountryId in the Staff entity? Of course it seems to be redundant to include a FK and its parent as FK, but I wanted to be clarified if there is some situations or requirements when using such a king of relations with cascade? Which one should be used?
I would avoid breaking normalization because there is no simple way to enforce that a staff's Country reference and it's City's Country reference are guraranteed to be in sync. For instance, a Staff might have a City set to "Toronto" with a Country set to "Canada", but then somewhere the City is updated to "Boston", but Staff.Country is not updated. Staff says country is "Canada" while it's City says country is "USA". Who is trusted as the source of truth?
When it comes to displaying information about staff, use View Models to flatten out relevant details. If you want to display staff details with a Country name and nothing else about the city, the view model can expose that based on data selected from the entities. For instance:
var staffViewModels = context.Staff
.Select(x => new StaffViewModel
{
StaffId = x.Id,
Name = x.Name,
Country = x.City.Country.Name
}).ToList();
Even if the structure introduced an Address for staff which consisted of a City which related to a country:
var staffViewModels = context.Staff
.Select(x => new StaffViewModel
{
StaffId = x.Id,
Name = x.Name,
Country = x.Address.City.Country.Name
}).ToList();
The entity can remain normalized and generate the SQL to efficiently access the relevant data.

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.

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 }

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.

Linq except return whole table

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.

Categories