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.
Related
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)
I have this table:
CREATE TABLE [dbo].[SandTable](
[Id] [uniqueidentifier] NOT NULL,
[Date] [date] NULL,
CONSTRAINT [PK_SandTable] PRIMARY KEY)
ALTER TABLE [dbo].[SandTable] ADD CONSTRAINT [DF_SandTable_Id] DEFAULT (NEWID()) FOR [Id]
Question is not about using NEWID() vs NEWSEQUENTIALID().
I use linqPad to test the table.
SandTables.InsertOnSubmit(new SandTable
{
// I don't provide any value for Id
Date = DateTime.Now
});
SubmitChanges();
My initial idea was to create an Id column that is able to initialize itself to a value when no Id is provided but will use the id provided when one is provided.
But because Guid is a struct, not a class the Id is never null, Id is initialized to his default value (00000000-0000-0000-0000-000000000000). So SQL server consider that Id has always a value and then the NEWID() default instruction is never called.
Is it possible to force the call to NEWID() on specific value? Should I use a trigger to evaluate the value of Id and when it's (00000000-0000-0000-0000-000000000000) then call NEWID()? What are the solutions or workaround?
You can do it with a check constraint:
ALTER TABLE [dbo].[SandTable]
ADD CONSTRAINT [DF_SandTable_Id] DEFAULT (NEWID()) FOR [Id]
ALTER TABLE [dbo].[SandTable]
WITH CHECK ADD CONSTRAINT [CK_SandTable_Id_Empty]
CHECK (
[Id] <> CAST(0x0 AS UNIQUEIDENTIFIER)
)
I have tried the following solution to try to do the insert/update data table into sql server, but some problems happended. http://www.aspsnippets.com/Articles/SqlBulkCopy--Bulk-Insert-records-and-Update-existing-rows-if-record-exists-using-C-and-VBNet.aspx
I created a table: People
CREATE TABLE [dbo].[People](
[ID] [varchar](10) NOT NULL,
[Name] [varchar](50) NULL,
[Email] [varchar](50) NULL,
[Country] [varchar](50) NULL
) ON [PRIMARY]
Create a user-defined table type : PeopleType
CREATE TYPE [dbo].[PeopleType] AS TABLE(
[ID] [varchar](10) NOT NULL,
[Name][varchar](50) NULL,
[Email][varchar](50) NULL
)
I try to use this table type to create a procedure:Update_People
CREATE PROCEDURE [dbo].[Update_People]
#tblpeople PeopleType READONLY
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO People p1
USING #tblpeople p2
ON p1.ID=p2.ID
WHEN MATCHED THEN
UPDATE SET p1.Name = p2.Name
,p1.Email = p2.Email
WHEN NOT MATCHED THEN
INSERT VALUES(p2.ID, p2.Name, p2.Email);
END
but when I try to use the user-defined table type to create the procedure, An SQL server Error happened.
"Column name or number of supplied values does not match table definition."
Did I do anything wrong or miss something?
Change your Insert statement to this if you don't want to add Countries:
INSERT INTO People(Id, Email, Name) VALUES(p2.ID, p2.Name, p2.Email);
The reason you receive the error is because you don't specify which columns to use the Insert statement expects 4 as 4 are defined in the table. But ou only provide 3.
The other option is to add the Country Property to your user defined type and add the country with the procedure:
CREATE TYPE [dbo].[PeopleType] AS TABLE(
[ID] [varchar](10) NOT NULL,
[Name][varchar](50) NULL,
[Email][varchar](50) NULL,
[Country][varchar](50) NULL
)
INSERT VALUES(p2.ID, p2.Name, p2.Email, p2.Country);
EDIT: I am not sure about the syntax, since I haven't used this in a while, but it could be that you only need to provide the column names like this:
INSERT (Id, Email, Name) VALUES(p2.ID, p2.Name, p2.Email);
I am getting the exception while adding object in database (Sqlite I am currently using).
Exception: The member with identity '' does not exist in the metadata collection. Parameter name: identity
Normally this code works on my local but I want to run this project my netbook too but whatever I do I cant find the way which make it run.
Any help will be greately appreciated.
-- Original table schema
CREATE TABLE [Content] (
[Id] integer PRIMARY KEY AUTOINCREMENT NOT NULL,
[Title] text NOT NULL,
[Content] text NOT NULL,
[PageId] integer NOT NULL,
[CreatedAt] datetime,
[UpdatedAt] datetime,
[CreatedBy] text,
[UpdatedBy] text,
CONSTRAINT [FK_Content_PageId_Page_Id] FOREIGN KEY ([PageId]) REFERENCES [Page] ([Id])
);
-- Original table schema
CREATE TABLE [Page] (
[Id] integer PRIMARY KEY AUTOINCREMENT NOT NULL,
[Title] text NOT NULL,
[Url] text NOT NULL,
[Visibility] bit NOT NULL,
[CreatedAt] datetime,
[UpdatedAt] datetime,
[CreatedBy] text,
[UpdatedBy] text
);
using (var entities = new PageEntities())
{
var page = entities.Pages.FirstOrDefault(p => p.Id == id);
if (page != null)
{
var content = new Content
{
Title = model.Title,
Explanation = model.Explanation,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
PageId = page.Id
};
entities.AddToContents(content);
entities.SaveChanges();
return RedirectToAction("PageContent/" + id, "Admin");
}
Ok guys (and gals), this one has been driving me nuts all night and I'm turning to your collective wisdom for help.
I'm using Fluent Nhibernate and Linq-To-NHibernate as my data access story and I have the following simplified DB structure:
CREATE TABLE [dbo].[Classes](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[StartDate] [datetime2](7) NOT NULL,
[EndDate] [datetime2](7) NOT NULL,
CONSTRAINT [PK_Classes] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[Sections](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[ClassId] [bigint] NOT NULL,
[InternalCode] [varchar](10) NOT NULL,
CONSTRAINT [PK_Sections] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[SectionStudents](
[SectionId] [bigint] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_SectionStudents] PRIMARY KEY CLUSTERED
(
[SectionId] ASC,
[UserId] ASC
)
CREATE TABLE [dbo].[aspnet_Users](
[ApplicationId] [uniqueidentifier] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[UserName] [nvarchar](256) NOT NULL,
[LoweredUserName] [nvarchar](256) NOT NULL,
[MobileAlias] [nvarchar](16) NULL,
[IsAnonymous] [bit] NOT NULL,
[LastActivityDate] [datetime] NOT NULL,
PRIMARY KEY NONCLUSTERED
(
[UserId] ASC
)
I omitted the foreign keys for brevity, but essentially this boils down to:
A Class can have many Sections.
A Section can belong to only 1 Class but can have many Students.
A Student (aspnet_Users) can belong to many Sections.
I've setup the corresponding Model classes and Fluent NHibernate Mapping classes, all that is working fine.
Here's where I'm getting stuck. I need to write a query which will return the sections a student is enrolled in based on the student's UserId and the dates of the class.
Here's what I've tried so far:
1.
var sections = (from s in this.Session.Linq<Sections>()
where s.Class.StartDate <= DateTime.UtcNow
&& s.Class.EndDate > DateTime.UtcNow
&& s.Students.First(f => f.UserId == userId) != null
select s);
2.
var sections = (from s in this.Session.Linq<Sections>()
where s.Class.StartDate <= DateTime.UtcNow
&& s.Class.EndDate > DateTime.UtcNow
&& s.Students.Where(w => w.UserId == userId).FirstOrDefault().Id == userId
select s);
Obviously, 2 above will fail miserably if there are no students matching userId for classes the current date between it's start and end dates...but I just wanted to try.
The filters for the Class StartDate and EndDate work fine, but the many-to-many relation with Students is proving to be difficult. Everytime I try running the query I get an ArgumentNullException with the message:
Value cannot be null.
Parameter name: session
I've considered going down the path of making the SectionStudents relation a Model class with a reference to Section and a reference to Student instead of a many-to-many. I'd like to avoid that if I can, and I'm not even sure it would work that way.
Thanks in advance to anyone who can help.
Ryan
For anyone who cares, it looks like the following might work in the future if Linq-To-NHibernate can support subqueries (or I could be totally off-base and this could be a limitation of the Criteria API which is used by Linq-To-NHibernate):
var sections = (from s in session.Linq<Section>()
where s.Class.StartDate <= DateTime.UtcNow
&& s.Class.EndDate > DateTime.UtcNow
&& s.Students.First(f => f.UserId == userId) != null
select s);
However I currently receive the following exception in LINQPad when running this query:
Cannot use subqueries on a criteria
without a projection.
So for the time being I've separated this into 2 operations. First get the Student and corresponding Sections and then filter that by Class date. Unfortunately, this results in 2 queries to the database, but it should be fine for my purposes.