In my database, I created the tables structure as follows.
CREATE TABLE Course
(
Course_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
);
CREATE TABLE Student
(
Stu_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
Mobile varchar(255),
Age int,
Course_ID int,
FOREIGN KEY (Course_ID) REFERENCES Course(Course_ID)
);
CREATE TABLE Subject
(
Sub_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
);
CREATE TABLE Teacher
(
Teach_ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(255) NOT NULL,
Mobile varchar(255)
);
CREATE TABLE Course_Subject
(
CouSub_ID int IDENTITY(1,1) PRIMARY KEY,
Course_ID int,
Sub_ID int,
FOREIGN KEY (Course_ID) REFERENCES Course(Course_ID),
FOREIGN KEY (Sub_ID) REFERENCES Subject(Sub_ID)
);
CREATE TABLE Teacher_Subject
(
TeachSub_ID int IDENTITY(1,1) PRIMARY KEY,
Teach_ID int,
Sub_ID int,
FOREIGN KEY (Teach_ID) REFERENCES Teacher(Teach_ID),
FOREIGN KEY (Sub_ID) REFERENCES Subject(Sub_ID)
);
Now my problem is I need to retrieve students data who learned from some teacher, which means need to retrieve some teacher's students who learned from his/her. To accomplish my requirement. I write this SQL query.
select
s.*
from
tbl_student s
inner join
Course_Subject tcs on s.Course_Id = tcs.Course_Id
inner join
Teacher_Subject tst on tst.Sub_ID = tcs.Sub_ID
inner join
Teacher t on t.Teach_ID = tst.Teach_ID
where
t.Teach_ID = #SomeTeacherId
Now I need to convert this query to a lambda expression or Linq. How can I do it? Please help me. Have any possible way to generate this using Visual Studio.
Well, you could use EF to generate object mapping to your tables. And use LINQ to rewrite your query with a slightly different syntax:
var result = from students in tbl_student
join subjects in Course_Subject on students.Course_Id == subjects.Course_Id
join ts in Teacher_Subject on subjects.Sub_ID == ts.Sub_ID
join teachers in Teacher on teachers.Teach_ID == ts.Teach_ID
where teachers.Teach_ID == "your_value"
select students;
Not sure it's an absolutely correct query, but I hope you'll get the main idea.
Have any possible way to generate this using Visual Studio.?
Yes, you can do this using Linq-to-SQL
for your query, this might be appropriated
var students = from student in db.Students
join tcs in db.CourseSubjects on student.CourseId equals tcs.CourseId
join tst in db.TeacherSubjects on tcs.SubId equals tst.SubId
join t in db.Teachers on tst.TeachId equals t.TeachId
where t.TeachId == someTeacherId
select student;
Lambda:
Students
.Where(x=> x.Course.Course_Subjects
.Any(y => y.Subject.Teacher_Subjects
.Any(z => z.Teach_ID == someTeacherId)
)
)
.Select(x => x)
Related
I have a SQL table that has two foreign keys and when I run Entity Data Model Wizard and select Code First from database, and then create the tables, my table won't show up as a class. It generates something in the primary model class that looks like this:
modelBuilder.Entity<User>()
.HasMany(e => e.Categories)
.WithMany(e => e.Users)
.Map(m => m.ToTable("UserCategory").MapLeftKey("UserID").MapRightKey("ID"));
But I don't know how to use that to add or delete from that table, since it won't show up as a class when I'm coding.
My tables are:
CREATE TABLE [User]
(
ID NVARCHAR(128) PRIMARY KEY,
FirstName VARCHAR(255) NOT NULL,
LastName VARCHAR(255),
JoinDate DATETIME,
ZipCode VARCHAR(25),
SearchRadius INT,
LoginToBusinessSide BIT
);
/*The categories businesses can fall under. */
CREATE TABLE Category
(
ID INT IDENTITY(1,1) PRIMARY KEY,
[Name] VARCHAR(255) UNIQUE NOT NULL,
);
/*The categories chosen by a specific user to get notified of*/
CREATE TABLE UserCategory
(
ID INT FOREIGN KEY REFERENCES Category(ID),
UserID NVARCHAR(128) FOREIGN KEY REFERENCES [User](ID),
CONSTRAINT PK_UserCategory PRIMARY KEY (ID, UserID)
);
How do I get UserCategory to show up as its own class, so I can easily access it?
I want to be able to just access it like every other class:
db.UserCategories.ID =
How can I
ADO doesn't create a class for my many to many table, but I can still access it. To add new categories to it, I use this code:
for(var i = 0; i < categories.Length; ++i)
{
var user = db.Users.Find(thisUser.ID);
var cat = db.Categories.Find(categories[i]);
user.Categories.Add(cat);
}
I have to an active connection to both tables that the foreign keys are linked to, and then when I add one to the Categories table, it goes to the correct place.
If you understand exactly why this works, or if there's a better way, please do comment.
I am experimenting with Dapper for the first time. I have two tables: Films and Ratings.
CREATE TABLE [dbo].[Films]
(
[Id] INT NOT NULL PRIMARY KEY,
[Title] VARCHAR(250) NOT NULL,
[Genre] VARCHAR(50) NOT NULL,
[RatingId] INT NOT NULL,
CONSTRAINT [FK_Films_To_Ratings] FOREIGN KEY (RatingId) REFERENCES Ratings(Id)
)
CREATE TABLE [dbo].[Ratings]
(
[Id] INT NOT NULL PRIMARY KEY,
[Name] VARCHAR(50) NOT NULL
)
I have written a stored procedure that will return all films in the Films table and joins with the Ratings table. Dapper works easily when I have the table structured using the same name between the FK and PK of the tables.
CREATE PROCEDURE [dbo].[GetFilms]
AS
BEGIN
SELECT
F.Id,
F.Title,
F.Genre,
F.RatingId,
R.Name
FROM
dbo.Films as F
INNER JOIN
dbo.Ratings as R
ON
F.RatingId = R.Id;
END
When my query runs, the film object becomes instantiated correctly but the RatingId was set to 0 (since int defaults to 0). The rating property contains the name, but the Id was also set to 0.
return this._db.Query<Film, Rating, Film>(
"dbo.GetFilms",
(f, r) =>
{
f.Rating = r;
return f;
},
splitOn: "RatingId",
commandType: CommandType.StoredProcedure
).ToList();
How can I successfully run my Dapper query and get the exact results I need when the column names are not identical like in my example? Table structure looks cleaner to me when I have columns named Ratings.Id instead of Ratings.RatingId.
Dapper will try and map property for property at the point you start splitting. You want your query to look like the following, and you can ditch the splitOn since you are splitting on Id.:
SELECT
F.Id,
F.Title,
F.Genre,
--Rating object starts here
R.Id,
R.Name
FROM
dbo.Films as F
INNER JOIN
dbo.Ratings as R
ON
F.RatingId = R.Id;
i use C# to display sql view in datagridview
i have the following view with hebrew for column names
CREATE VIEW [fixes_view]
AS
SELECT f.fixId AS N'מס תיקון',
f.receiveDate AS N'ת.קבלה',
c.clientName AS N'שם לקוח',
m.modelName AS N'דגם',
f.problem AS N'תיאור תקלה',
f.comments AS N'הערות',
e.employeeName AS N'שם עובד',
f.priceOffer AS N'מחיר ראשונ',
f.price AS N'מחיר סופי',
f.returned AS N'הוחזר'
FROM fixes f
INNER JOIN clients c
ON f.clientId = c.clientId
INNER JOIN modelist m
ON f.modelID = m.modelID
INNER JOIN employees e
ON f.employeeId = e.employeeId
when i want to use it in C# and call it with another condition using
public DataTable GetAllActiveFixTable()
{
return genericGetFixTable("WHERE returned=0;");
}
i tried to refer to the "AS" name 'הוחזר' but it gives me an error when i call it
error:
Invalid column name 'returned'.
private DataTable genericGetFixTable (string str)
{
return genericGetTable("select * FROM [fixes_view] " + str);
}
create table fixes (
fixId int IDENTITY(1,1) primary key,
receiveDate date not null,
clientId int not null,
modelID int not null,
problem nvarchar(100) not null,
comments nvarchar(50),
employeeId int not null,
priceOffer real,
price real,
returned bit,
foreign key (clientId)
references clients,
foreign key (modelID)
references modelist,
foreign key (employeeId)
references employees)
I have two tables in SQL server for customers and their addresses.
CREATE TABLE Customers
(
ID INT NOT NULL IDENTITY(1,1),
LastName VARCHAR(50) NOT NULL,
FirstName VARCHAR(50) NOT NULL,
DateOfBirth DATETIME2 NOT NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED ([ID] ASC)
)
CREATE TABLE CustomerAddresses
(
ID INT NOT NULL IDENTITY(1,1),
CustomerID INT NOT NULL CONSTRAINT [FK_CustomerAddresses_Customers] FOREIGN KEY([CustomerID]) REFERENCES [dbo].[Customers] ([ID]),
Street VARCHAR(100) NOT NULL,
City VARCHAR(50) NOT NULL,
Country VARCHAR(50) NOT NULL,
CONSTRAINT [PK_CustomerAddresses] PRIMARY KEY CLUSTERED ([ID] ASC)
)
I have generated a EFdatamodel and connecting to it using DataContext. I am trying to get all customers for a particular country. My code is as follows.
static List<Customer> GetByCountry(string country)
{
MyDbContext MyContext = new MyDbContext ();
return MyContext.Customers.Where(x => x.CustomerAddresses.Where( y => y.Country == country)).ToList();
}
But I am getting following compilation errors.
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable' to
'bool' Cannot convert lambda expression to delegate type
'System.Func' because some of the return
types in the block are not implicitly convertible to the delegate
return type
What am I doing wrong here?
Your code must be
return MyContext.Customers.Where(x => x.CustomerAddresses.Any( y => y.Country == country)).ToList();
Because you want to return all Customers that have any address with the specified country. Where() expects a function that returns whether the condition is true, and returns an enumeration of all elements which hold this condition true. In your outer Where() your supply an argument that is of type IEnumerable (which is the return value of your inner where), and that is wrong.
I have a SqlQuery that looks like this:
SqlQuery query =
DB.Select(
Order.Schema.TableName + ".*",
OrderDetail.Schema.TableName + ".*")
.From<Order>()
.InnerJoin<OrderDetail>()
.Where(Order.IdColumn).IsEqualTo(1);
Now I would expect the Method SqlQuery.ExecuteJoindDataSet() to generate a DataSet for me, that contains 2 DataTables (one for Orders, one for OrderDetails) and put a DataRelation into the DataSet, so I don't have to do this all by hand.
But ExecuteJoinedDataSet() only generates one Table containing all the data from Order but not from OrderDetail:
// Order = 104 Columns
// OrderDetail = 74 Columns
query.ExecuteJoinedDataSet().Tables.Count => 1
query.ExecuteJoinedDataSet().Tables[0].Columns.Count => 104
query.ExecuteDataSet().Tables[0].Columns.Count => 177
I think I am on the right way, but can someone please tell me, what I am doing wrong?
The purpose of this is that the Printing Component I use in my project does not accept generic objects, but DataSet's as a DataSource.
ExecuteJoinedDataSet actually uses all the table columns from the first table and replaces the value in any column that has a foreign key with the first non-forgeign-key value from the corresponding row in the foreign table. It does inner joins for non-null foreign-key columns, and left joins for nullable ones.
So for this schema
create table tblBaseType
(
id int not null primary key identity(1,1),
name not null varchar(100) unique
)
create table tblBaseLocation
(
id int not null primary key identity(1,1),
name not null varchar(100) unique
)
create table tblBase
(
id int not null primary key identity(1,1),
name varchar(100) not null unique,
baseTypeID int not null references tblBaseType(id),
baseLocationID int null references tblBaseLocation(id)
)
and a SqlQuery like
SqlQuery q = new Select().From(TblBase.Schema).Where(TblBase.IdColumn).IsEqualTo(1);
DataSet ds = q.ExecuteJoinedDataSet();
this approximate sql would be generated:
select tblBase.Id,
tblBase.Name,
tblBaseType.Name as baseTypeId,
tblBaseLocation.name as baseLocationId
from tblBase
inner join tblBaseType on tblBase.baseTypeID = tblBaseType.id
left join tblBaseLocation on tblBase.baseLocationID = tblBaseLocation.id
The actual sql is fully qualified, this is just a rough from-scratch approximation.