I cannot figure out why my return from a linq query always is not correct.
[HttpGet]
public List<Programs> GetPrograms()
{
using (var context = new ProgramsDataContext1())
{
var qry = (from a in context.Programs
join b in context.courselist on a.Prog_id equals(b.prog_id)
where a.Prog_id ==b.prog_id
orderby a.Programname
select new
{ Prog_id =a.Prog_id,Programname=a.Programname, programlevel=a.programlevel, planname=a.planname, catalogNo=b.catalogNO, coursetitle=b.coursetitle, subject=b.subject
}
).ToList();
return qry ;
}
}
It always has a red underline on the qry. What is the problem here? Thanks.
Since you are doing the join already, you do not need the where clause. Also your return type is not the same, that's the error you are getting. You are right now returning a list of anonymous objects, not Programs
Just define a class that lists just the properties you need from the two classes and instead of building an anonymous object create instances of this class.
public class ProgramsCourseDto
{
public int Prog_id {get;set;}
public string Programname {get;set;}
public int programlevel {get;set;}
public string planname {get;set;}
public int catalogNo {get;set;}
public string coursetitle {get;set;}
public string subject {get;set;}
}
[HttpGet]
public List<ProgramsCourseDto> GetProgramsCourses()
{
using (var context = new ProgramsDataContext1())
{
var qry = (from a in context.Programs
join b in context.courselist on a.Prog_id equals(b.prog_id)
orderby a.Programname
select new ProgramsCourseDto
{
Prog_id =a.Prog_id,
Programname=a.Programname,
programlevel=a.programlevel,
planname=a.planname,
catalogNo=b.catalogNO,
coursetitle=b.coursetitle,
subject=b.subject
}).ToList();
return qry ;
}
}
Related
Is there any way to execute following query with native NHibernate linq provider?
var result =
(from e1 in Session.Query<Entity1>()
join e2 in Session.Query<Entity2>() on e1.SomeField equals e2.SomeField into je
from je2 in je.DefaultIfEmpty()
select new {e1.Id, e1.SomeField, je2.SomeUrelatedField}).ToList()
Currently I'm using Fluent NHibernate 1.2 with NHibernate 3.1 and I get NotImplementedException
I don't want to introduce any relation between e1 and e2. By design they have no a relation and query like above could be used in rare purposes.
This blog post tells that it was unsupported. What about now?
I'm not quite sure when this was introduced but this is now supported by NHibernate. I am using version 3.3.1 and I have a query very similar to yours working well. The test below works for me:
[TestFixture]
public class NHibernateJoinUnrelatedEntitiesTest
{
private ISessionFactory sessionFactory;
[Test]
public void I_Can_Join_Unrelated_Entities()
{
// Arrange
ISession session = sessionFactory.OpenSession();
// Act
var results = (
from c in session.Query<Customer>()
from wal in session.Query<WebsiteActivityLog>()
where c.Id == wal.CustomerId
&& c.Id == 54856
select new { CustomerId = c.Id, Name = c.FirstName, Address = wal.IpAddress }
).ToList();
// Assert
Assert.NotNull( results );
}
public class Customer
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
}
public class WebsiteActivityLog
{
public virtual int Id { get; set; }
public virtual int CustomerId { get; set; }
public virtual string IpAddress { get; set; }
}
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id( x => x.Id );
Map( x => x.FirstName );
}
}
public class WebsiteActivityLogMap : ClassMap<WebsiteActivityLog>
{
public WebsiteActivityLogMap()
{
Id( x => x.Id );
Map( x => x.CustomerId );
Map( x => x.IpAddress );
}
}
}
Not using LINQ, but you can do theta joins when using HQL.
Select e1.Id, e1.SomeField, e2.SomeUnrelatedField
from Entity1 e1, Entity2 e2 where e1.SomeField = e2.SomeField
However, you won't be able to do outer joins with this. So if that's a requirement, you'll have to go with raw SQL.
It's still not supported.
You should either introduce a relation between the objects or use SQL for the query.
I have the following viewmodel,
public class SiteAdminCreateViewModel
{
public Customer Customer { get; private set; }
public CustomerSite CustomerSite { get; private set; }
public SelectList CustomerNames { get; private set; }
public SiteAdminCreateViewModel(CustomerSite customerSite, Customer customer)
{
CustomerSite = customerSite;
Customer = customer;
CustomerNames = new SelectList(customer.CustomerName);
}
}
And the following methods in my repository for returning a list of customers and a list of CustomerSites
public IQueryable<CustomerSite> GetCustomerSites
{
get { return context.CustomerSites; }
}
public IQueryable<Customer> GetCustomers
{
get { return context.Customers; }
}
When i instanitiate the viewmodel in my controller im wanting to return the list of customers to passs to the select list in the viewmodel.
public ViewResult Create()
{
CustomerSite customerSite = new CustomerSite();
var customer = repository.GetCustomers.ToList();
return View(new SiteAdminCreateViewModel(customerSite, customer));
}
But the return line throws the error
cannot convert from System.Collections.Generic.List' to 'CustomerOrders.Domain.Entities.Customer
I think this is because i have the customer variable defined in the Viewmodel of type Customer but im trying to pass a list of customers?
Can anyone offer any advice on where i am going wrong here?
Do i need to define both the Customer type and the CustomerNames select list type in the viewmodel, i defined the Customer Object only so i can use it to pass the Customers to the select list but im not sure if this is the best way to do this?
Any advice anyone can offer for a newbie, will be much appreciated.
Your SiteAdminCreateViewModel class' constructor is defined as follows:
public SiteAdminCreateViewModel(CustomerSite customerSite, Customer customer) {
...
}
Its second argument is of type Customer.
You're passing var customer = repository.GetCustomers.ToList() to it, whose type is List<Customer>.
When i instanitiate the viewmodel in my controller im wanting to
return the list of customers to passs to the select list in the
viewmodel.
If I understand what you're saying correctly, you're just trying to pass the customers list to build a SelectList.
First of all, you seem to be passing a string to the SelectList constructor. This would not even compile (read System.Web.Mvc.SelectList).
What you'd need to do is change SiteAdminCreateViewModel's constructor like
public SiteAdminCreateViewModel(CustomerSite customerSite, IEnumerable<Customer> customers) {
/* ... */
CustomerNames = new SelectList(customers, "CustomerId", "CustomerName");
}
CustomerId and CustomerName being properties of the Customer class.
it's simply because you are trying to pass IList into constructor of the SiteAdminCreateViewModel
var customer = repository.GetCustomers.ToList();
return View(new SiteAdminCreateViewModel(customerSite, customer));
using
var customer = repository.GetCustomers.ToList().FirstOrDefault();
return View(new SiteAdminCreateViewModel(customerSite, customer));
would work, also you may need to check if the customer is null
I am fairly new to MVC, but after playing with it (MVC 3/Razor), I am hooked.
I have a few questions:
1) What is the best, or most widely used pattern to develop MVC apps in? Repository, DDD, UOW?
2) I am using the Entity Framework 4, so could some please explain to me or point me to a good source that will explain the Repository Pattern w/EF4? Doesn't EF4 take place as the business layer and the data access layer? Does the Repository Pattern even provide a benefit?
3) Also, one last question, could someone explain the whole relationship between the Controller, the Model and the View? I get the basics, but maybe a little more in depth of the correct way to use it. View Models - Say I have a view that displays customer info, and one that edits it, should I have a view model and an edit model, or can the be passed around?
4) Examples??
Thanks for the help up front,
$("Sam")
** EDIT **
Am I on the right track here:
Public Class HomeController
Inherits System.Web.Mvc.Controller
Function Index(ByVal id As Integer) As ActionResult
Return View(New HomeModel)
End Function
<HttpPost()> _
Function Index(ByVal Model As HomeModel) As ActionResult
Return View(Model)
End Function
End Class
Public Class HomeModel
Private _Repository As IRepository(Of Customer)
Public Property Customer As Customer
Public Sub New()
End Sub
Public Sub New(ByVal ID As Integer)
_Repository = New CustomerRepository
Customer = _Repository.GetByID(ID)
End Sub
End Class
Public Interface IRepository(Of T)
Function GetByID(ByVal ID As Integer) As T
Sub Add(ByVal Entity As T)
Sub Delete(ByVal Entity As T)
End Interface
Public Class CustomerRepository
Implements IRepository(Of Customer)
Public Sub Add(ByVal Entity As Customer) Implements IRepository(Of Customer).Add
End Sub
Public Sub Delete(ByVal Entity As Customer) Implements IRepository(Of Customer).Delete
End Sub
Public Function GetByID(ByVal ID As Integer) As Customer Implements IRepository(Of Customer).GetByID
Return New Customer With {.ID = ID, .FirstName = "Sam", .LastName = "Striano"}
End Function
End Class
Public Class Customer
Public Property ID As Integer
Public Property FirstName As String
Public Property LastName As String
End Class
I use generic repositories that get instantiated in a service class (using Dependency Injection with Ninject).
The service class essentially performs two functions:
It provides all the methods that the controller will consume.
It has a property called ViewModel, that essentially maps the data that the views need into a MyViewModel class.
The Controller consumes the service class. With this "pattern", your controllers look like:
namespace ES.eLearningFE.Areas.Courses.Controllers
{
public partial class CourseController : Controller
{
ICourseDisplayService service;
public CourseController(ICourseDisplayService service)
{
this.service = service;
}
public virtual ActionResult Display(int CourseId, int StepOrder, string PupilName, string TutorName)
{
service.CourseId = CourseId;
service.StepOrder = StepOrder;
service.PupilName = PupilName;
service.TutorName = TutorName;
if (Request.IsAjaxRequest())
{
return PartialView(service.ViewModel);
}
else
{
return View(service.ViewModel);
}
}
}
}
The ViewModel class only hold display data and no methods (except the odd really simple method to retrieve data from another property that is, for example a List<> object).
Works really well. An example of a service class:
namespace ES.eLearning.Domain.Services.Courses
{
public class SqlCourseDisplayService : ICourseDisplayService
{
DataContext db;
public SqlCourseDisplayService(DbDataContextFactory contextFactory)
{
db = contextFactory.Make();
CoursesRepository = new SqlRepository<Course>(db);
StepsRepository = new SqlRepository<CourseStep>(db);
StepLinksRepository = new SqlRepository<StepLink>(db);
UserCoursesRepository = new SqlRepository<UserCourse>(db);
CourseTutorsRepository = new SqlRepository<CourseTutor>(db);
UsersRepository = new SqlRepository<User>(db);
}
#region ICourseDisplayService Members
public ViewModels.CourseDisplayVM ViewModel
{
get
{
return new ViewModels.CourseDisplayVM
{
CourseId = this.CourseId,
CourseName = this.Course.Name,
Steps = this.Steps,
ActiveStepIndex = this.ActiveStepIndex,
CurrentStepIndex = this.CurrentStepIndex,
Pupil = new UserDto { UserId = this.PupilId, UserName = this.PupilName },
Tutors = this.GetTutors(this.CourseId),
Tutor = tutorName == null ? null : new UserDto { UserName = this.TutorName, UserId = this.TutorId}
};
}
}
#region Entities
int courseId;
public int CourseId
{
get
{
if (courseId == 0) throw new ApplicationException("Invalid Course Id!");
return courseId;
}
set
{
if (value == 0) throw new ApplicationException("Invalid Course Id!");
try
{
Course = (from c in CoursesRepository.Query where c.CourseId == value select c).First();
Steps = Course.CourseSteps.ToList();
courseId = value;
}
catch {throw new ApplicationException("No Course found for Course Id: " + value);}
}
}
public Data.Course Course { get; private set; }
public int StepOrder { get; set; }
public List<Data.CourseStep> Steps { get; private set; }
public int ActiveStepIndex
{
get
{
if (PupilName == null)
{
throw new ApplicationException("Pupil not set!");
}
if (CourseId == 0)
{
throw new ApplicationException("Course not set!");
}
try
{
var x = (from uc in UserCoursesRepository.Query where (uc.IdCourse == CourseId) && (uc.UserName == PupilName) select uc).First();
return x.ActiveStepIndex;
}
catch { throw new ApplicationException("Could not get Active Step!"); }
}
}
#endregion
#region Users
string tutorName;
public string TutorName
{
get
{
if (tutorName == null) throw new ApplicationException("Invalid call to get Tutor Name [Null Tutor Name]!");
return tutorName;
}
set
{
tutorName = value;
TutorId = (Guid)Membership.GetUser(tutorName).ProviderUserKey;
}
}
public Guid TutorId { get; set; }
string pupilName;
public string PupilName
{
get { return pupilName; }
set
{
pupilName = value;
PupilId = (Guid)Membership.GetUser(pupilName).ProviderUserKey;
}
}
public Guid PupilId { get; set; }
#endregion
#region Utility Properties
public int CurrentStepIndex { get; set; }
public int StepCount
{
get
{
return Steps == null ? 0 : Steps.Count();
}
}
#endregion
#region Private Utilities
private List<UserDto> GetTutors(int CourseId)
{
return (from ct in CourseTutorsRepository.Query join u in UsersRepository.Query
on ct.TutorName equals u.UserName
where (ct.CourseId == courseId)
select new UserDto { UserName = ct.TutorName, UserId = u.UserId }).ToList();
}
#endregion
#region Repositories
private IRepository<Course> CoursesRepository
{
get;
set;
}
private IRepository<CourseStep> StepsRepository
{
get;
set;
}
private IRepository<StepLink> StepLinksRepository
{
get;
set;
}
private IRepository<UserCourse> UserCoursesRepository
{
get;
set;
}
private IRepository<CourseTutor> CourseTutorsRepository
{
get;
set;
}
private IRepository<User> UsersRepository
{
get;
set;
}
#endregion
#endregion
}
}
May not be everyone's choice, but hey, it works for me... AND (more importantly) my clients and their users.
Edit
As requested in the comment below, the Repository that I use:
namespace ES.eLearning.Domain
{
public class SqlRepository<T> : IRepository<T> where T : class
{
DataContext db;
public SqlRepository(DataContext db)
{
this.db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Attach(T entity)
{
db.GetTable<T>().Attach(entity);
}
public void Save()
{
db.SubmitChanges();
}
#endregion
}
}
And the IRepository Interface:
namespace Wingspan.Web.Mvc
{
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> FetchAll();
IQueryable<TEntity> Query {get;}
void Add(TEntity entity);
void Delete(TEntity entity);
void Attach(TEntity entity);
void Save();
}
}
This should help you getting started. There are a lot of tutorials and videos available; for example:
Understanding Models, Views and Controllers
The ASP.NET MVC 2.0 basics and excellent introduction by Scott Hanselman. Personally one of my favorite speakers.
And also at www.asp.net; there are a few tutorials/examples to help you getting started. For example the Music Store sample
Unfortunately, I'm not so familiar with EF4/Repository pattern. But here's a blogpost about this pattern.
1) I would say that the repository pattern is the most widely used, then there is inversion of controll too.
2) I can't really point out the benefits with using a repository for entity framework other than that the controller should not know about how to acces data other then asking a repository. This makes it easy to switch it out sometime.
You can also eager load the data to make sure that the view don't call the database in every iteration of a foreach, for example a collection of users to display data from a child entity. You can probly do this anyway, but I feel that the repository is the right place to do it.
3) I can't tell you about the concept in a more in depth way, but I can tell some about viewmodels. In my opinion you should only use viewmodels if there is anything more then one entity you want to send to the view, for example a list of countries. You can alo use a viewmodel to "flatten" out very complex objects.
I would defiantly say the repository pattern is used a lot. This pattern can be used with Dependency Injection. Using Dependency Injection makes Unit Testing a breeze because you can snap different repositories to an abstract repoistory. Check out http://ninject.org/ for a simple to use Dependecy injector for .NET.
View Models should hold display data and transfer that data from the controller to the view. If you want to edit and display customer info, take a look at this
I have a custom List (MyCustomList) that implements List(Of MyCustomClass).
I want to run a LINQ query against that and return a filtered MyCustomList.
Public ReadOnly Property DebitTransactions As MyCustomList
Get
Return From item In Me Where item.IsDebit = True Select item
End Get
End Property
I get a type conversion here because the LinQ query doesn't return the list in the same MyCustomList that it was filtering. It cannot convert a WhereSelectListIterator object (which is returned) to a MyCustomClass.
I really need the filtered results to be in the same format they came in as. Any suggestions?
If you implement your own Where exthension method you can keep using linq syntax.
public class MyCustomList : List<MyCustomClass>
{
public MyCustomList() : base()
{
}
public MyCustomList(IEnumerable<MyCustomClass> coll) : base(coll)
{
}
}
public static class MyCustomListExtensions
{
public static MyCustomList Where(this MyCustomList myList, Func<MyCustomClass, bool> predicate)
{
return new MyCustomList(Enumerable.Where(myList, predicate));
}
}
public class MyCustomClass
{
public int Int1 { get; set; }
public string Str1 { get; set; }
}
And here I'm using the custom Where implementation:
var myList = new MyCustomList()
{
new MyCustomClass() { Int1 = 1},
new MyCustomClass() { Int1 = 2},
new MyCustomClass() { Int1 = 3},
};
MyCustomList filteredList = from item in myList where item.Int1 > 1 select item;
Assert.AreEqual(2, filteredList.Count);
You have to iterate the list, add them to a collection, and return the collection. Linq doesn't support, directly, conversion of iterators to custom return types other than List, arrays and Dictionaries.
Not sure if what I am trying is possible or not, but I'd like to reuse a linq expression on an objects parent property.
With the given classes:
class Parent {
int Id { get; set; }
IList<Child> Children { get; set; }
string Name { get; set; }
}
class Child{
int Id { get; set; }
Parent Dad { get; set; }
string Name { get; set; }
}
If i then have a helper
Expression<Func<Parent,bool> ParentQuery() {
Expression<Func<Parent,bool> q = p => p.Name=="foo";
}
I then want to use this when querying data out for a child, along the lines of:
using(var context=new Entities.Context) {
var data=context.Child.Where(c => c.Name=="bar"
&& c.Dad.Where(ParentQuery));
}
I know I can do that on child collections:
using(var context=new Entities.Context) {
var data=context.Parent.Where(p => p.Name=="foo"
&& p.Childen.Where(childQuery));
}
but cant see any way to do this on a property that isnt a collection.
This is just a simplified example, actually the ParentQuery will be more complex and I want to avoid having this repeated in multiple places as rather than just having 2 layers I'll have closer to 5 or 6, but all of them will need to reference the parent query to ensure security.
If this isnt possible, my other thought was to somehow translate the ParentQuery expression to be of the given type so effectively:
p => p.Name=="foo";
turns into:
c => c.Dad.Name=="foo";
but using generics / some other form of query builder that allows this to retain the parent query and then just have to build a translator per child object that substitutes in the property route to the parent.
EDIT:
Following on from comments by #David morton
Initially that looks like I can just change from Expression to a delegate function and then call
.Where(ParentQuery()(c.Dad));
However I am using this in a wider repository pattern and cant see how I can use this with generics and predicate builders - I dont want to retrieve rows from the store and filter on the client (web server in this case). I have a generic get data method that takes in a base expression query. I then want to test to see if the supplied type implements ISecuredEntity and if it does append the securityQuery for the entity we are dealing with.
public static IList<T> GetData<T >(Expression<Func<T, bool>> query) {
IList<T> data=null;
var secQuery=RepositoryHelperers.GetScurityQuery<T>();
if(secQuery!=null) {
query.And(secQuery);
}
using(var context=new Entities.Context()) {
var d=context.GetGenericEntitySet<T>();
data=d.ToList();
}
return data;
}
ISecuredEntity:
public interface ISecuredEntity : IEntityBase {
Expression<Func<T, bool>> SecurityQuery<T>();
}
Example Entity:
public partial class ExampleEntity: ISecuredEntity {
public Expression<Func<T, bool>> SecurityQuery<T>() {
//get specific type expression and make generic
Type genType = typeof(Func<,>).MakeGenericType(typeof(ExampleEntity), typeof(bool));
var q = this.SecurityQuery(user);
return (Expression<Func<T, bool>>)Expression.Lambda(genType, q.Body, q.Parameters);
}
public Expression<Func<ExampleEntity, bool>> SecurityQuery() {
return e => e.OwnerId==currentUser.Id;
}
}
and repositoryHelpers:
internal static partial class RepositoryHelpers {
internal static Expression<Func<T, bool>> SecureQuery<T>() where T : new() {
var instanceOfT = new T();
if (typeof(Entities.ISecuredEntity).IsAssignableFrom(typeof(T))) {
return ((Entities.ISecuredEntity)instanceOfT).SecurityQuery<T>();
}
return null;
}
}
EDIT Here is the (eventual) solution
I ended up going back to using expressions, and using LinqKit Invoke. Note: for EF I also had to call .AsExpandable() on the entitySet
The key part is being able to call:
Product.SecureFunction(user).Invoke(pd.ParentProduct);
so that I can pass in the context into my parent query
My end classes look like:
public interface ISecureEntity {
Func<T,bool> SecureFunction<T>(UserAccount user);
}
public class Product : ISecureEntity {
public Expression<Func<T,bool>> SecureFunction<T>(UserAccount user) {
return SecureFunction(user) as Expression<Func<T,bool>>;
}
public static Expression<Func<Product,bool>> SecureFunction(UserAccount user) {
return f => f.OwnerId==user.AccountId;
}
public string Name { get;set; }
public string OwnerId { get;set; }
}
public class ProductDetail : ISecureEntity {
public Expression<Func<T,bool>> SecureFunction<T>(UserAccount user) {
return SecureFunction(user) as Expression<Func<T,bool>>;
}
public static Func<ProductDetail,bool> SecureFunction(UserAccount user) {
return pd => Product.SecureFunction(user).Invoke(pd.ParentProduct);
}
public int DetailId { get;set; }
public string DetailText { get;set; }
public Product ParentProduct { get;set; }
}
Usage:
public IList<T> GetData<T>() {
IList<T> data=null;
Expression<Func<T,bool>> query=GetSecurityQuery<T>();
using(var context=new Context()) {
var d=context.GetGenericEntitySet<T>().Where(query);
data=d.ToList();
}
return data;
}
private Expression<Func<T,bool>> GetSecurityQuery<T>() where T : new() {
var instanceOfT = new T();
if (typeof(Entities.ISecuredEntity).IsAssignableFrom(typeof(T))) {
return ((Entities.ISecuredEntity)instanceOfT).SecurityQuery<T>(GetCurrentUser());
}
return a => true; //returning a dummy query
}
}
Thanks for the help all.
You're overthinking it.
First, don't return an Expression<Func<Parent, bool>>, that'll require you to compile the expression. Return simply a Func<Parent, bool> instead.
Next, it's all in how you call it:
context.Children.Where(c => c.Name == "bar" && ParentQuery()(c.Dad));
context.Parents.Where(ParentQuery());