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;
}
Related
I am creating an invoice like this:
For signed in users, I save the invoices and the invoice units to database (one invoice has many invoice units) and for users that are not signed in, I am trying to save the data into sessions
[HttpPost]
public ActionResult Create(Invoice invoice)
{
var userId = User.Claims.FirstOrDefault(c => c.Type == "UserId")?.Value;
if (userId is not null)
{
invoice.UserId = Guid.Parse(userId.ToString());
DateTime dateTime = DateTime.Now;
invoice.DateCreated = dateTime;
foreach (var invoiceUnit in invoice.InvoiceUnits)
{
db.InvoiceUnits.Add(invoiceUnit);
}
db.Add(invoice);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
invoice.Id = Guid.NewGuid();
var invoicesFromSession = GetInvoicesFromSession();
var invoiceUnitsFromSession = GetInvoiceUnitsFromSession();
DateTime dateTime = DateTime.Now;
invoice.DateCreated = dateTime;
if (invoice is not null)
{
invoicesFromSession.Add(invoice);
HttpContext.Session.SetString("invoice", JsonSerializer.Serialize(invoicesFromSession));
foreach(var invoiceUnit in invoice.InvoiceUnits)
{
invoiceUnit.Id = new Guid();
invoiceUnit.InvoiceId = invoice.Id;
HttpContext.Session.SetString("invoiceUnit", JsonSerializer.Serialize(invoiceUnitsFromSession));
invoiceUnitsFromSession.Add(invoiceUnit);
}
}
return RedirectToAction("Index");
}
}
I am getting the invoice units from session like this:
private List<InvoiceUnit> GetInvoiceUnitsFromSession()
{
HttpContext.Session.LoadAsync();
var sessionString = HttpContext.Session.GetString("invoiceUnit");
if (sessionString is not null)
{
return JsonSerializer.Deserialize<List<InvoiceUnit>>(sessionString);
}
return Enumerable.Empty<InvoiceUnit>().ToList();
}
And then I am trying to call the function in the Edit controller
var sessionInvoices = GetInvoicesFromSession();
var sessionInvoiceUnits = GetInvoiceUnitsFromSession();
var invoiceFromDbSession = sessionInvoices.FirstOrDefault(i => i.Id == id);
List<InvoiceUnit> invoiceUnitsForInvoiceSession = new List<InvoiceUnit>();
foreach (var invoiceUnit in sessionInvoiceUnits)
{
if (invoiceUnit.InvoiceId == id)
{
invoiceUnitsForInvoiceSession.Add(invoiceUnit);
}
}
GenericModel sessionData = new GenericModel(invoiceUnitsForInvoiceSession, invoiceFromDbSession);
return View(sessionData);
From some reason tho, when I call the GetInvoiceUnitsFromSession(); in the Edit controller to retrieve the wanted invoice unit for the specific invoice, I only receive one invoice unit for each invoice (the first one I have entered). When I debug the invoiceUnitsFromSession variable in the create function, the number of units fits just fine for the specific invoice so I think there must be some problem in the way I am trying to retreive the session. Any idea what changes to make in order to retreive all of the invoice units I recieve for all invoices so I can get them in Edit controller?
The issue you see comes from this block:
foreach(var invoiceUnit in invoice.InvoiceUnits)
{
invoiceUnit.Id = new Guid();
invoiceUnit.InvoiceId = invoice.Id;
HttpContext.Session.SetString("invoiceUnit", JsonSerializer.Serialize(invoiceUnitsFromSession)); // Specifically this line
invoiceUnitsFromSession.Add(invoiceUnit);
}
Here you're writing the value for the key invoiceUnit on each repetition of the loop before you actually update the value, so at least the last line will always be missing. You would want to either change the order:
foreach(var invoiceUnit in invoice.InvoiceUnits)
{
invoiceUnit.Id = new Guid();
invoiceUnit.InvoiceId = invoice.Id;
invoiceUnitsFromSession.Add(invoiceUnit);
HttpContext.Session.SetString(
"invoiceUnit",
JsonSerializer.Serialize(invoiceUnitsFromSession));
}
or move the line that stores invoice units into the session out of the loop completely to avoid unnecessary repetition:
foreach(var invoiceUnit in invoice.InvoiceUnits)
{
invoiceUnit.Id = new Guid();
invoiceUnit.InvoiceId = invoice.Id;
invoiceUnitsFromSession.Add(invoiceUnit);
}
HttpContext.Session.SetString(
"invoiceUnit",
JsonSerializer.Serialize(invoiceUnitsFromSession));
call a list of objects from a session
Do you want the below way?
Configure your SessionExtension like below:
public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonSerializer.Serialize(value));
}
public static T? Get<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonSerializer.Deserialize<T>(value);
}
}
Then use methods like below:
//// your list object
List<MyClass> classCollection = new List<MyClass>();
//// To set value in session
HttpContext.Session.Set<List<MyClass>>("someKey", classCollection);
//// To Get Value from Session
List<MyClass> classCollection = HttpContext.Session.Get<List<MyClass>>("someKey");
Read Set and get Session values to know more.
I have two classes: User and Site. User and Site have a many-to-many relationship. A Site object S has a property indicating whether or not a User U should be validated before U is added to S. To validate a User, the application retrieves validation rules from the Site and checks to see that the User's properties' values match the validation rules' values. If they all match/pass, the User is "valid" to be added to that Site.
How would you structure this relationship? My first thought is to create an intermediate class (i.e. Mediator design pattern?) that has a field of type IEnumerable<User> and Site so I can encapsulate the Site validation setting retrieval. Also, I'm thinking of adding an "IsValid" property to the User class. Is that all I need? I want to make sure things are not tightly coupled.
Thoughts?
Here's similar code I wrote up:
public class User
{
public int _userId;
public string _fname;
public string _lname;
public User(string connectionString, int id)
{
using (var dc = new DataContext(connectionString))
{
var user = dc.Users.SingleOrDefault(u => u.ID == id);
_userId = user.ID;
_fname = user.FName;
_lname = user.LName;
}
}
public bool IsValidUser(int siteId)
{
bool isValid = true;
// logic here probably won't change
var conditions = Site.GetConditions(_userId);
// e.g. checks _fname, _lname
return Site.UserMeetsConditions(_id, conditions);
}
}
public class Site
{
public int _siteId;
public List<Setting> _siteSettings;
public Site(string connectionString, int id)
{
using (var dc = new DataContext(connectionString))
{
var site = dc.Sites.SingleOrDefault(u => u.ID == id);
_siteId = site.ID;
}
}
public void SetSiteSettings(string connectionString)
{
using (var dc = new DataContext(connectionString))
{
_siteSettings = dc.SiteSettings.Select(s => s).ToList();
}
}
public bool SiteRequiresValidityCheck()
{
return _siteSettings.Any(s => s.SettingID = 100 && s.Value == true);
}
}
public Validator
{
public List<User> users;
public bool _requiresValidityCheck;
public bool UsersAreValid(int siteId)
{
bool usersAreValid = true;
if (_requiresValidityCheck)
{
foreach (var user in users)
{
if (!user.IsValid)
{
usersAreValid = false;
break;
}
}
}
return usersAreValid;
}
}
static void Main()
{
string cs = myconnectionstring;
var user1 = new User(cs, 1);
var user2 = new User(cs, 2);
List<User> users = new List<User>() { user1, user2 };
var site = new Site(cs, 10);
site.SetSiteSettings(cs);
var validator = new Validator();
validator.Users = users;
validator._requiresValidityCheck = site.SiteRequiresValidityCheck();
bool usersAreValid = validator.UsersAreValid(site._siteId);
}
If this is a POCO class or a MODEL you could use DataAnnotations on your class attributes.
Like user
[Required]
etc attributes for each attribute.
Data annotations also has support for cross attribute checking that you can implement those too.
take a look at them here:
https://msdn.microsoft.com/en-us/library/dd901590%28VS.95%29.aspx
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();
}
}
}
I have a function that (via ajax) I pass a Guid and a comma delimited string of the types of objects I would like to return . I'm having trouble building a link statement that only returns the desired types. I'm struggling with how to build the query to check if string[] relatedTypes matches rw.GetType().Name. Or perhaps there's a better way.
Here's the Model...
public abstract class WebObject : IValidatableObject
{
public WebObject()
{
this.Id = Guid.NewGuid();
RelatedTags = new List<Tag>();
RelatedWebObjects = new List<WebObject>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public virtual ICollection<WebObject> RelatedWebObjects { get; set; }
public IList<Guid> RelatedWebObjectIds { get; set; }
}
And here's my function
public JsonResult GetRelatedWebObjectsByWebObject(Guid id, string relatedWebObjectTypes)
{
JsonResult result = new JsonResult();
Guid webSiteId = db.WebObjects.Find(id).WebSiteId;
string[] relatedTypes = relatedWebObjectTypes.Split(',');
var resultData = (from w in db.WebObjects
where w.Id == id
from rw in w.RelatedWebObjects
where rw.GetType().Name.Contains(relatedTypes)
select rw.Id).ToList();
result.Data = resultData;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
Are you looking for something like:
var relatedTypes = new HashSet<string>(relatedWebObjectTypes);
var resultData = (from w in db.WebObjects
where w.Id == id
&& relatedTypes.SetEquals
(w.RelatedWebObjects.Select(rwo => rwo.GetType().Name))
select w.RelatedWebObjectIds).ToList();
Although I would say that it isn't good practice to use a collection of simple type names in this manner. Are you sure you couldn't use a Type[] or similar here?
It's not clear from your question what exactly do you want, but I think it's this:
from w in db.WebObjects
where w.Id == id
from rw in w.RelatedWebObjects
where relatedWebObjectTypes.Contains(rw.GetType().Name)
select rw.Id
This selects all the items from WebObjects with the correct Id (I guess there should be only one, but it does not matter to the query). And for each of them, get the RelatedWebObjects whose type's name is in relatedWebObjectTypes. And for each of those, get their Id.
You would need to refactor a bit, instead of passing in the name of the types as string, you should pass the actual type then use the linq operator for OfType(Of relatedType)
The MSDN Article gives a simple example that should have you on your way.
A little late, but here's what I ended up going with...
public JsonResult GetRelatedWebObjectsByWebObject(Guid id, string relatedWebObjectTypes)
{
JsonResult result = new JsonResult();
Guid webSiteId = db.WebObjects.Find(id).WebSiteId;
List<string> relatedTypes = new List<string>(relatedWebObjectTypes.Split(','));
var resultData = (from w in db.WebObjects
where w.Id == id
from rw in w.RelatedWebObjects
select rw).ToList();
result.Data = resultData.Where(w => relatedTypes.Contains(w.GetType().BaseType.Name) == true).Select(w => new { Id = w.Id, Type = w.GetType().BaseType.Name }).ToList();//w.Id).Select(w => w.GetType().BaseType.Name).ToList();
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
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.