I create a project where I use EF with LINQ and Model first. So, based on my edmx I created my Database and also my classes.
So I got some problems. I created a Click to test if my code is working.
protected void btnSearch_Click(object sender, EventArgs e)
{
ZUser Zusr = new ZUser();
List<ZUser> lst = Zusr.ListAll();
// Zusr.Id = 1;
string test = "";
foreach (ZUser item in lst)
{
test = item.Name;
}
lblName.Text = test;
}
So in my ZUser Class (Controller) I did the following code:
[Serializable]
public class ZUser : User
{
String connString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
public List<ZUser> ListAll()
{
List<ZUser> lstUser = new List<ZUser>();
using (DataContext db = new DataContext(connString))
{
Table<User> Users = db.GetTable<User>();
var query =
from usr in Users
where usr.Name == "Test"
select usr;
foreach (ZUser usr in query)
lstUser.Add(usr);
}
return lstUser;
}
}
And my Model (Class generated by my edmx)
namespace System.Model
{
//[Table]
public partial class User
{
public int Codigo { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public DateTime Created { get; set; }
public DateTime LastLogin { get; set; }
}
}
Problems
If I don't let the [Table] in my Model class (I added that) I got this error. I'm not sure if this is the right way to correct it.
The type '{0}' is not mapped as a Table.
After "fixing" the problem from above. I got this new one in my foreach (ZUser usr in query).
The member '{0}.{1}' has no supported translation to SQL.
I don't know how to fix or create a workaround this one.
Amazing, this feature of linq!
Really intresting!
After some searches on msdn and test it in application,
maybe you miss the Column attribute over all single class members:
[Column(CanBeNull = false, DbType = "int")]
And maybe you must uncomment the Table attribute on top of User declaration
Hope this help!
Related
I am working with the EF6 and I am a big fan of the dynamic proxies, which enables lazy loading and change tracking. Anyway I am not happy, that the lazy loading is triggered once the property is accessed instead of loading the data, when the enumerator or the count property is called first. Therefore I tried to diesable the proxys and replace them by custom proxies. It was an easy thing to use a custom object context and overload the CreateObject method. Unfortantly the ObjectMaterialized event cannot replace the entity and I am not able to replace an entity from a query. The creation of the object lies deep in internal classes of the framework.
Has anybody an idea how to use custom proxies? Or how I am able to replace the entities materialized in an object query?
You should .Include the properties you want to fetch so that you avoid an N+1 query problem.
public class User
{
public int Id { get; set; }
public string Name { get; set ;}
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set ; }
public int AuthorId { get; set; }
public virtual User Author { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string Note { get; set ;}
public int PostId { get; set; }
public virtual Post Post { get; set; }
public int AuthorId { get; set; }
public virtual User Author { get; set; }
}
public class BlogContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<Comment> Comments { get; set; }
}
Then this is BAD in that it'll do tons of queries:
using (var db = new BlogContext())
{
var user = db.Users.Single(u => u.Id=5)); // +1 query
foreach (var post in user.Posts) // N queries
{
var message = String.Format("{0} wrote {1}", user.Name, post.Title);
Console.WriteLine(message);
foreach (var comment in post.Comments) // N * M queries!
{
// and that .Author make N * M MORE!
var message = String.Format("\t{0} commented {1}", comment.Author.Name, comment.Note);
Console.WriteLine(message);
}
}
}
And this is GOOD in that it'll do one query:
using (var db = new BlogContext())
{
var user = db.Users
.Single(u => u.Id=5))
.Include(u => u.Posts) // eliminates the N post queries
.Include(u => u.Posts.Comments) // eliminates the M comment queries
.Include(u => u.Posts.Comments.Author); // eliminates the M comment author queries
foreach (var post in user.Posts) // N queries
{
var message = String.Format("{0} wrote {1}", user.Name, post.Title);
Console.WriteLine(message);
foreach (var comment in post.Comments) // N * M queries!
{
// and that .Author make N * M MORE!
var message = String.Format("\t{0} commented {1}", comment.Author.Name, comment.Note);
Console.WriteLine(message);
}
}
}
Can anyone help me to solve this problem?
I am using visual studio2010 and its windows phone 7 application
I have created addpet.xaml and mypet.xaml.
Created IsolatedStorageSetting object in mypet.cs file
{
public static IsolatedStorageSettings settings=IsolatedStorageSettings.ApplicationSettings;
}
I have 5 textboxes and I am storing its value in list item.That list stores in IsolatedStorageSetting object.
{
SaveMypet savepet = new SaveMypet();
savepet.Name = txt_name.ToString();
savepet.Birthday = txt_birthday.ToString();
savepet.FavFood = txt_favouritefood.ToString();
savepet.DocNo = txt_doctorsno.ToString();
savepet.VacDate = txt_vacdate.ToString();
savepet.FavToy = txt_favouritetoy.ToString();
// savepet.Image1 = image1.Source;
listMyPet.Add(savepet);
settings.Add("iso_listMyPet", listMyPet);
}
Now I want to access this object in addpet.cs and cast it to list and then want to assign to listbox.
Like this, I have did but does not work
Created list object in addpet.cs
{
static List<pg_addPet> list_listMyPet = null;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
list_listMyPet = (List<pg_addPet>)pg_addPet.settings["iso_mypet_list"];
listbox_mypet.ItemsSource = list_listMyPet;
}
And my SaveMypet class is
public class SaveMypet
{
public string Name { get; set; }
public string Birthday { get; set; }
public string FavFood { get; set; }
public string DocNo { get; set; }
public string VacDate { get; set; }
public string FavToy { get; set; }
// public ImageSource Image1 { get; set; }
}
You've declared the settings property as static. Therefore, you need to use the class name to access it:
list_listMyPet = (List<pg_addPet>)pg_mypet.settings["iso_mypet_list"];
Try the following:
if(!pg_mypet.settings.TryGetValue("iso_mypet_list", out list_listMyPet))
{
list_listMyPet = new List<pg_addPet>();
}
This will try to retrieve the value and if if fails it will create an empty list instead.
I've inherited my first MVC project and it involves using MVC3 on top of Linq to SQL. I've been trying to find a way to generate a check box list based on a many to many relationship involving a cross table.
I have a systemFailureType table that maps to a SystemFailureProblem table via a cross table.
Here is my designer layout for the tables:
here my view model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using XNet.Repository.Model;
namespace XNet.WebUI.Hotel.ViewModel
{
public class CheckFacilityVM
{
public int FacilityID { get; set; }
public string facilityName { get; set; }
public bool facilityAvailable { get; set; }
public virtual Facility facility { get; set; }
public virtual HotelFacility hotelfacility { get; set; }
}
}
here my controller
public ActionResult Facility()
{
ViewBag.hotel = _hotelService.GetByID(1).HotelName;
var model = db.Facilities
.Select(htl => new CheckFacilityVM
{
FacilityID = htl.FacilityID,
facilityName = htl.FacilityName,
facilityAvailable = htl.IsActive,
})
.ToList();
return View(model);
}
and here my constructor
public Facility ShowRoomFacility(int HotelID)
{
var x = (from d in db.Facilities
where d.FacilityID == HotelID
select d).FirstOrDefault();
return x;
}
how can i make this.....
I'll provide you a simple, more common example that you can adapt for your purposes - Users and Roles (a user can be assigned to many roles and likewise a role can have many users).
Assume we have an "Update User" form where we want to set the roles the user belongs to.
Here's what the controller/view model would look like:
public class UsersController : Controller {
[HttpGet]
public ActionResult Update(int id) {
var user = db.Users.Find(id);
var model = new UsersUpdateModel {
Name = user.Name,
SelectedRoles = user.Roles.Select(r => r.Id).ToList(),
Roles = GetRolesSelectList()
};
return View(model);
}
[HttpPost]
public ActionResult Update(UsersUpdateModel model) {
var user = db.Users.Find(model.Id);
var roles = db.Roles.ToList();
foreach (var role in roles) {
if (model.SelectedRoles.Contains(role.Id)) {
user.AddRole(role);
}
else {
user.RemoveRole(role);
}
}
}
public SelectList GetRolesSelectList() {
var roles = db.Roles.OrderBy(r => r.Name).ToList();
return new SelectList(roles, "Id", "Name");
}
}
public class UsersUpdateModel {
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<int> SelectedRoles { get; set; }
public SelectList Roles { get; set; }
}
Essentially you need to add a property to your view model to hold the available roles (in this example, "Roles") and one to hold the selected roles (in this example, "SelectedRoles").
In your POST action you can then load all the roles and, if the Id exists in UsersUpdateModel.SelectedRoles you add the role to the user, otherwise you remove it.
I tend to encapsulate the process of adding/removing the Role (or whatever collection it may be) in the side that owns the relationship - for example, User.AddRole would probably check to see if the role already exists to prevent adding it twice:
public void AddRole(Role role) {
var exists = this.Roles.FirstOrDefault(r => r.Id == role.Id);
if (exists == null) {
Roles.Add(role);
}
}
Finally to create the Checkbox list you can use the helper I created here. It would look something like:
#Html.CheckBoxListFor(model => model.SelectedRoles, Model.Roles)
That should give you enough to go on. Note that the code was written in notepad so is probably not copy/pastable.
I'm using the mongo-csharp-driver to query my Mongo entities.
I have the following objects which are stored in the Mongo:
public class Table
{
public int Id { get; private set; }
public string Description{ get; private set; }
public List<Player> Players { get; private set; }
public Table()
{
}
}
public class Player
{
public int Id { get; private set; }
public string Username{ get; private set; }
public Player()
{
}
}
When I'm trying to query the "Table" object by id or description, I get the appropriate results, but when I try to query by the list of player, I get null:
// Works ok
var tab1 = mongo.GetCollection<Table>().Where(g => g.Description == "Test");
// Always return null, although should return the same result
var tab2 = mongo.GetCollection<Table>().Where(g => g.Players.Count > 90).FirstOrDefault();
What am I missing here?
Thanks,
Nir.
The issue is that Count property is translated into the $size query operator.
From the linked Advanced Queries page you can see that:
"You cannot use $size to find a range of sizes (for example: arrays
with more than 1 element)."
Windows Phone 7.1 supports SQL Server CE and LINQ to SQL, as well as upgrading the database via DatabaseSchemaUpdater.
On other platforms I would read the database schema tables (e.g. sys.objects) to view the current schema and work out what tables/columns need to be upgraded.
Given that no direct SQL access is allowed on Windows Phone, how can retrieve the current database schema?
SQL Server CE still includes the INFORMATION_SCHEMA.TABLES and INFORMATION_SCHEMA.COLUMNS tables, but it is a little tricky to access them as no direct SQL access is allowed.
However, you can create a DataContext which maps to these tables:
public class SchemaContext : DataContext
{
public SchemaContext()
: base("Data Source=isostore:/Database.sdf")
{
if (!this.DatabaseExists())
{
throw new InvalidOperationException("Cannot use the SchemaContext on a database which doesn't exist");
}
}
public Table<Table> Tables;
public Table<Column> Columns;
[Table(Name = "INFORMATION_SCHEMA.Columns")]
public class Column
{
[Column(Name = "TABLE_NAME")]
public string TableName { get; set; }
[Column(Name = "COLUMN_NAME")]
public string Name { get; set; }
[Column(Name = "DATA_TYPE")]
public string DataType { get; set; }
[Column(Name = "ORDINAL_POSITION")]
public int OrdinalPosition { get; set; }
[Column(Name = "IS_NULLABLE")]
public string IsNullableString { get; set; }
public bool IsNullable
{
get { return this.IsNullableString == "YES"; }
set { this.IsNullableString = value ? "YES" : "NO"; }
}
}
[Table(Name = "INFORMATION_SCHEMA.Tables")]
public class Table
{
[Column(Name = "TABLE_NAME")]
public string Name { get; set; }
[Column(Name = "TABLE_TYPE")]
public string Type { get; set; }
}
}
You can then read the schema with the following code:
using (var schemaContext = new SchemaContext())
{
foreach (var table in schemaContext.Tables)
{
}
}
It's important to create a separate context for these tables, as otherwise the DataContext.CreateDatabase call will attempt to create these schema tables, which will fail.
There is a Walkthrough for Updating a Local Database Application for Windows Phone on MSDN which advocates using the DatabaseSchemaVersion on the DatabaseSchemaUpdater - i.e:
// Set the new database version.
DatabaseSchemaUpdater dbUpdater = db.CreateDatabaseSchemaUpdater();
dbUpdater.DatabaseSchemaVersion = APP_VERSION;
dbUpdater.Execute();
You can query the version and add the bits that you add in each release, without having to worry about the current schema (after all, it'll be a known configuration as long as you remember to keep the version numbers updated correctly.)