I have a UnitOfWork/Service pattern where I populate my model using NHibernate before sending it to the view. For some reason I still get the YSOD, and I don't understand why the object collection is not already populated.
My controller method looks like this:
public ActionResult PendingRegistrations()
{
var model = new PendingRegistrationsModel();
using (var u = GetUnitOfWork())
{
model.Registrations = u.UserRegistrations.GetRegistrationsPendingAdminApproval();
}
return View(model);
}
The service/unit of work looks like this:
public partial class NHUserRegistrationRepository : IUserRegistrationRepository
{
public IEnumerable<UserRegistration> GetRegistrationsPendingAdminApproval()
{
var r =
from UserRegistration ur in _Session.Query<UserRegistration>()
where ur.Status == AccountRegistrationStatus.PendingAdminReview
select ur;
NHibernateUtil.Initialize(r);
return r;
}
}
What am I doing wrong?
The problem you are having is no different than the problem you would have with any other LINQ provider. You need to execute your query in order to get the results. If you don't have a valid context, that won't work.
This problem is easy to fix without condemning LINQ to NHibernate. Just change
public IEnumerable<UserRegistration> GetRegistrationsPendingAdminApproval()
{
var r =
from UserRegistration ur in _Session.Query<UserRegistration>()
where ur.Status == AccountRegistrationStatus.PendingAdminReview
select ur;
NHibernateUtil.Initialize(r);
return r;
}
to
public IEnumerable<UserRegistration> GetRegistrationsPendingAdminApproval()
{
var r =
from UserRegistration ur in _Session.Query<UserRegistration>()
where ur.Status == AccountRegistrationStatus.PendingAdminReview
select ur;
NHibernateUtil.Initialize(r);
return r.ToList();
}
Related
I need to write a function called IsExists(string TableName,string KeyColumnName,string ValueToCheck) in DAL which checks whether the data exists in the particular table and in the particular column which I am passing
Basically I want to achieve something like this when I try to put up in sql query
select count(id) from "+TableName+" where "+keyColumnName+"="+ValueToCheck+";
But I cant use sql query ..
In my solution I have an .edmx-file, an entity class along with a repository class, which has SearchFor method:
public class EntityRepository<C, TEntity> : IEntityRepository<TEntity>
where TEntity : class
where C : DbContext
{
public IQueryable<TEntity> SearchFor(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate)
{
return _entities.Set<TEntity>().Where(predicate);
}
}
I Tried something like this
public bool CheckIsExists<T>(string keyColumnName, string valueToCheck) where T : class
{
bool isExist = false;
using (var repository = ContextFactory.CreateEmployeeMasterRepository())
{
var repo = repository.GetEntityRepository<T>();
object obj = (T)Activator.CreateInstance(type);
repo.SearchFor(u => u.GetType().GetProperty(keyColumnName).GetValue(obj).ToString() == valueToCheck);
}
return isExist;
}
Which is again not working ..
Somebody help me in doing this. i have been trying from long time.. suggestions are greatly appreciated.
Here's how I would solve this type of problem. You could convert it to function if you like.
// Let's say I have a Customers table and want to search against its Email column
// First I get my data layer class that inherits from DbContext class
yourContextClass db = new yourContextClass();
// below I am getting valueToCheck from a view with GET method
public ActionResult Index(string valueToCheck)
{
bool isExists = false;
IEnumerable<Customers> customersList = (from cus in db.Customers select cus).ToList();
int index = customersList.FindIndex(c => c.Email == valueToCheck);
if (index >= 0)
isExists = True;
// if index is -1 then the value to check does not exist
return View();
}
You can execute sql query from you dbcontext:
using (var ctx = new DBEntities())
{
var itemsCount = ctx.Database.SqlQuery<int>("select count(id) from "+TableName+" where "+keyColumnName+" = "+ValueToCheck+").FirstOrDefault<int>();
}
I have stumbled upon a problem with Entity Framework this morning.
I have following code mapping a modified entity and saving it into database.
public Group Save(Group x)
{
using (var db = new HostContext())
{
db.Projects.Attach(x.Project);
if (x.ID != 0)
{
db.AttachableObjects.Attach(x);
var manager = ((IObjectContextAdapter)db).ObjectContext.ObjectStateManager;
manager.ChangeObjectState(x, EntityState.Modified);
}
else
{
db.AttachableObjects.Add(x);
}
db.SaveChanges();
return x;
}
}
I call Save method with existing group as a parameter. Group contains one user I want to add as a member.
The method finishes successfully, however the relationship is not persisted in database.
Any help is very appreciated.
EDIT: These are my classes
class User : AttachableObject
{
...
private List<Group> memberof;
[DataMember]
[InverseProperty("Members")]
public List<Group> MemberOf
{
get { return memberof; }
set { memberof = value; }
}
...
}
class Group : AttachableObject
{
...
private List<User> members;
[DataMember]
[InverseProperty("MemberOf")]
public List<User> Members
{
get { return members; }
set { members = value; }
}
...
}
EDIT2: This is where the Save method is called
public Group AcceptInvite(int id)
{
var mapper = new InviteMapper();
var userMapper = new UserMapper();
var groupMapper = new GroupMapper();
var invite = mapper.Find(id);
if (invite != null)
{
var group = groupMapper.Find(invite.GroupID);
var user = userMapper.Find(invite.InviteeID);
group.Members.Add(user);
mapper.Delete(invite.ID);
return groupMapper.Save(group);
}
return null;
}
EDIT3: My mappers
public class GroupMapper
{
public Group Find(int id)
{
using (var db = new HostContext())
{
return db.AttachableObjects
.Include("Project")
.OfType<Group>().FirstOrDefault(x => x.ID == id);
}
}
}
The rest of the mappers is the same, only using their own tables.
You are not changing the relationship info of Project, you are only setting x to modified, relationship info must be changed explicitly.
So x.Project must have some property that points back to Group, you need to set it so the change is recorded.
I am guessing that x is resurrected via some deserialization process?
I have the following code and I cannot achieve saving the changes.
The parameter of my method is a string containing the RefCode of a product I want to modify in the database, then the query is pulling the BaseProduct that is supposed to be modified.
(I tried to simplify the code and set it in English, so I have probably introduced some syntactic errors, but in my code in debug mode, I get all the info FROM the DB). Is there something wrong with the "select new" in the Linq query ?
public static void UpdateProduct(ViewProduct productToUpdate)
{
using (var context = new my_Entities())
{
var BaseProduct = (from prod in context.Product
where prod.Ref == productToUpdate.BaseProduct.RefPrd
select new ViewBaseProduct
{
RefPrd = prod.Ref,
DescrPrd = prod.DescrPrd,
NormeCe = (bool)prod.NormeCE
}).FirstOrDefault();
if (BaseProduct != null)
{
//BaseProduct.NormeCe = false;
BaseProduct = productToUpdate.BaseProduct;
context.SaveChanges();
}
}
}
But BaseProduct is a ViewBaseProduct object, is ViewBaseProduct a entity class? It seems it is a ViewModel class.
You have to get de Product entity, modify his fields and savechanges. It seems you only apply changes to the ViewModel class.
Try this:
public static void UpdateProduct(ViewProduct productToUpdate)
{
using (var context = new my_Entities())
{
var BaseProduct = (from prod in context.Product
where prod.Ref == productToUpdate.BaseProduct.RefPrd)
.FirstOrDefault();
if (BaseProduct != null)
{
//BaseProduct.NormeCe = false;
BaseProduct.field1 = productToUpdate.BaseProduct.field1;
BaseProduct.field2 = productToUpdate.BaseProduct.field2;
//update the necesary fields
//......
context.SaveChanges();
}
}
}
This won't work that way. You should use the CurrentValues.SetValues() method:
contexte.Entry(BaseProduct).CurrentValues.SetValues(productToUpdate.BaseProduct);
I think you have to Try this
public static void UpdateProduct(ViewProduct productToUpdate)
{
using (var contexte = new my_Entities())
{
var BaseProduct = (from prod in contexte.Product
where prod.Ref == productToUpdate.BaseProduct.RefPrd
select new ViewBaseProduct
{
RefPrd = prod.Ref,
DescrPrd = prod.DescrPrd,
NormeCe = (bool)prod.NormeCE
}).FirstOrDefault();
if (BaseProduct != null)
{
BaseProduct.BaseProduct.RefPrd=productToUpdate.BaseProduct.RefPrd
BaseProduct.BaseProduct.DescrPrd=productToUpdate.BaseProduct.DescrPrd
BaseProduct.BaseProduct.NormeCE==(bool)productToUpdate.BaseProduct.NormeCE
contexte.SaveChanges();
}
}
}
Hi I have created a class to get values form my customer's account table, I have created a class for that. I want to inform AccountId and the Field of the table I want the result back (for example FirstName). What is the best way to achieve this? I got something like the below as my alternative but I can't make it work...
This is how I want to get the result of first name:
LabelFirstName.Text = Manage.GetAccount(2, "FirstName"); // where 2 is the id I informed and FirstName is the Column I want to retrieve from the table.
the result would be "John" for example.
This is what I have:
public class Manage
{
public Manage()
{
}
public static string GetAccount(int AccountId, string Field)
{
LinqSqlDataContext contextLoad = new LinqSqlDataContext();
var q = (from p in contextLoad.MyAccounts
where p.AccountId == AccountId
select p).Single();
string var = q.?? // ?? would be my Field string "FirstName" for example
return var;
}
}
Please help
Thanks
I suggest you return the Account object, and then retreive the property where you need it, like this :
public static Account GetAccount(int AccountId)
{
LinqSqlDataContext contextLoad = new LinqSqlDataContext();
var q = (from p in contextLoad.MyAccounts
where p.AccountId == AccountId
select p).Single();
return q;
}
public void myMethod()
{
var account = GetAccout(2);
var accountName = account.FirstName;
var accountNumber = account.Number;
// ... and so on
}
If this is realy not helpful, you can use reflection like mentioned in other posts.
Good luck.
string value = (string)q.GetType().GetProperty(Field).GetValue(q, null);
You can return the Object of the class
public static Object GetAccount(int AccountId)
{
LinqSqlDataContext contextLoad = new LinqSqlDataContext();
var q = (from p in contextLoad.MyAccounts
where p.AccountId == AccountId
select p).FirstOrDefault();
return q;
}
var Account = GetAccount(int AccountId) as Account;
LabelFirstName.Text = Account.FirstName;
LabelLastName.Text = Account.LastName;
You can get all the field from the object !! So task will be achievable from one database call
A DataReader might be useful in this situation:
var q = from p in contextLoad.MyAccounts
where p.AccountId == AccountId
select p;
using (var command = dc.GetCommand(q))
{
command.Connection.Open();
using (var reader = command.ExecuteReader())
{
// expecting one row
if(reader.Read())
{
return reader.GetString(reader.GetOrdinal(Value));
}
}
return null;
}
ok, i have to admit that until now i still do not know the best way to return multiple objects using linq to sql.
public IList<Course> GetAllStudentCourses()
{
IList<Course> output = new List<Course>();
using (lenDataContext db = new lenDataContext())
{
var result =
from ct in db.CourseByTutors
join c in db.Courses on ct.CourseId equals c.Id
join u in db.Users on ct.TutorId equals u.Id
select new
{
c,
u,
};
foreach (var r in result)
{
Course course = new Course();
course.CourseByTutor = new CourseByTutor();
course = r.c;
course.IsGroupString = (r.c.IsGroup == 1) ? "Yes" : "No";
course.User = r.u;
output.Add(course);
}
}
return output;
}
I would like to return Course and User objects back to UI.
private void InitializeData()
{
Course c = new Course();
dgCourses.AutoGenerateColumns = false;
bs.DataSource = c.GetAllStudentCourses().ToList();
dgCourses.DataSource = bs; //bs is bindingsource
}
How do i display the user data e.g. Name to the Gridview?
i have put User.Name to the datapropertyName but it still showing nothing.
my Course.User has value.
If you return db.CourseByTutors you should have access to both the users and the courses. The two inner joins you are doing above seem unessecary because you should be able to access them via EntitySet. Just use the navigation properties to access all the users and courses.
public IQueryable<CourseByTutors> GetAllStudentCourses()
{
lenDataContext db = new lenDataContext();
return db.CourseByTutors;
}
Then in your gridview you can reference the properties by Coures.property and Users.property on a databound column. You can't use a using statement though because as soon as you return the IQueryable you would dispose of the datacontext.
You can flatten your object by wrapping them in another object :
public class CourseDisplay
{
private Course course;
public CourseDisplay(Course course)
{
this.course = course;
}
public string CourseName
{
get { return course.Name; }
}
public string UserName
{
get { return course.User.Name;}
}
}
It is simpler to bind to a child property in ObjectListView.