I'm creating a view with a drop list and some other fields that will update a database. In the model there are properties that map to the database and some properties that are used for the dropdownlistfor. The unmapped properties throws an exception. Is there a good way to exclude the drop list properties from being mapped? I tried putting them in a separate class in the model and that didn't work.
The model:
[Table("cardata")]//Links the external table to this model object
public class Cardata
{
//Maps to the database
public int id { get; set; }
public int dealerID { get; set; }
public string model { get; set; }
public int numCyl { get; set; }
public double weight { get; set; }
// UNMAPPED Used for a drop list of car names
public string carModel { get; set; }
public IEnumerable<SelectListItem> carList
{
get
{
cartableContext ctc = new cartableContext();
IEnumerable<SelectListItem> retVal = ctc.cardata.GroupBy(c => c.model).Select(cl => cl.FirstOrDefault()).Select(cars => new SelectListItem { Value = cars.id.ToString(), Text = cars.model.ToString() });
return retVal;
}
set { }
}
}
Could you use [NotMapped]?
[NotMapped]
public string carModel { get; set; }
[NotMapped]
public IEnumerable<SelectListItem> carList{...}
Related
I have the following method that returns a list of factory cars.
It works, but the ordering is wrong.
CarEngines can have an orderId and I want to order by that.
Looking at other answers on here, I see that you can't do an order by inside the query and you have to do it afterwards.
The problem is, I can't access CarEngines as you can see below:
public async Task<ActionResult<CountryList>> GetCountryCarObject(Guid countryID)
{
var factoryCars = await _context.CountryList
.Include(n => n.CarList).ThenInclude(l => l.CarEngines)
.Include(n => n.CarList).ThenInclude(l => l.CarOptions)
.SingleOrDefaultAsync(c => c.CountryId == countryID);
factoryCars.CarList.CarEngines <== CarEngines doesn't show up in CarList object
return factoryCars;
}
It is telling me that CarList doesn't contain a definition for CarEngines.
But it is in my CarList model, I have it defined like so:
public CarList()
{
CarEngines = new HashSet<CarEngines>();
}
public virtual ICollection<CarEngines> CarEngines { get; set; }
Here are the two models:
public partial class CarList
{
public CarList()
{
CarEngines = new HashSet<CarEngines>();
CarOptions = new HashSet<CarOptions>();
}
public string CarId { get; set; }
public string CarMake { get; set; }
public string CarModel { get; set; }
public Guid? CarCountryId { get; set; }
public virtual ICollection<CarEngines> CarEngines { get; set; }
public ICollection<CarOptions> CarOptions { get; set; }
}
public partial class CountryList
{
public CountryList()
{
CarList = new HashSet<CarList>();
}
[Key]
public Guid CountryId { get; set; }
public string CountryName { get; set; }
public string CountryLocation { get; set; }
public string CountryDesc { get; set; }
public virtual ICollection<CarList> CarList { get; set; }
}
So I'm not sure it doesn't see it.
Is there a way to get this to work?
Thanks!
Ok so the fact that there is something called CarList but is not a List is super confusing but moving on....
The issue is that CarList is a List. So use something like factoryCars.CarList.Select( x=>x.CarEngines). Also rename that to var country instead of var factoryCars since you return a single country and not a list of cars.
Also rename your variables and classes this confusion was probably caused by this. For example instead of having ICollection<CarList> CarList you can rename it into ICollection<Car> Cars so right now from the name you can easilly understand there are multiple cars (thus its a collection) which includes the object Car
I have a project where I have a set of forms:
public class Form
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> FieldValueIds { get; set; }
public string UserId { get; set; } // the user who completed the form.
public string FormTemplateId { get; set; }
}
Which each "implement" a form template selected at creation of the form.
public class FormTemplate
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> FieldIds { get; set; }
}
Which defines which fields are present within the form. Each field
public class FormField
{
public string Id { get; set; }
public string Name { get; set; }
public string Caption { get; set; }
public ValueType DataType { get; set; } // Enum specifying the type of data this field accepts.
}
Stores information about the field such as a description and what type it is expecting. Each FormField can be present in multiple FormTemplates with the values for the form being stored as FieldValue objects related to the Form itself.
public class FieldValue
{
public string Id { get; set; }
public string FieldId { get; set; }
public string ValueAsJsonString { get; set; }
}
Other objects include the User Object:
public class User
{
public string Id { get; set; }
public string Username { get; set; }
public string GivenNames { get; set; }
public string Surname { get; set; }
}
I would like to be able to perform a query to find all Forms completed by a user with a specified name, or all Forms where a field with name X has value Y and so forth.
I have looked into usage of indexes as specified in the documentation Indexing related documents, however the implementation as presented in the documentation threw a NotSupportedException when I implemented the example as follows:
class FormTemplates_ByFieldAndName : AbstractIndexCreationTask<FormTemplate>
{
public class Result
{
public string Name { get; set; }
public IList<string> FieldNames { get; set; }
}
public FormTemplates_ByFieldAndName()
{
Map = FormTemplates => from FormTemplate in FormTemplates
select new
{
Name = FormTemplate.Name,
FieldNames = FormTemplate.FieldIds.Select(x => LoadDocument<FormField>(x).Name)
};
}
}
// in code:
IList<FormTemplate> TestResults = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>()
.Where(x => x.Name == "TemplateName" || x.FieldNames.Contains("FieldName"))
.OfType<FormTemplate>()
.ToList();
As best as I can tell this was implemented correctly, however I have seen a suggestion to replace the .Contains with a .Any implementation instead. In lieu of this I have been experimenting with a different approach by applying successive .Where arguments. Like so:
var pre = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>();
var pr2 = pre.Where(x => x.Name == "TypeTest25");
List<FormTemplate> TestResults = pr2
.Where(x => x.FieldNames.Any(a => a == "field25"))
.OfType<FormTemplate>()
.OrderByScoreDescending()
.ToList();
Modifying the system to perform in a more factory oriented approach by applying successive filters based on a supplied string in a pre-specified format.
Is this the way I should be going for this implementation and if not what should I be changing? In particular if I am to proceed with the Indexing option how would I apply this technique to the nested relationship between Forms and FormFields through FormTemplates.
You seems to be trying to do this in a way that is mostly relational, but you don't have to.
Instead of trying to have a set of independent documents that each has part of the data, just store it all in a single document.
public class Form
{
public string Id { get; set; }
public string Name { get; set; }
public IList<FieldValue> FieldValues { get; set; }
public string UserId { get; set; } // the user who completed the form.
public string FormTemplateId { get; set; }
}
public class FieldValue
{
public string Id { get; set; }
// can store the value directly!
//public string ValueAsJsonString { get; set; }
public object Value {get; set; }
}
This will generate documents that looks like this:
{
"Id": "forms/1234",
"Name": "Tom",
"FieldValues": [
{
"Id": "FromValues/SchoolDistrictName",
"Value": "ABi195"
}
],
"UserId": "users/tom",
"FormTemplateId": "FromTemplate/1234"
}
Which is a much more natural way to model things.
At that point, you can use RavenDB's ability to index dynamic data, see the docs here:
https://ravendb.net/docs/article-page/3.5/Csharp/indexes/using-dynamic-fields
I am new in MVC. I am working on a project where i have created a model class and also context class which is working good if i view the record in normal view.
but if i try to get the data in group by "Series_Name" and bind it into same model class it gives error. here is my code
Here is Model class and DBContextClass
[Table("tblvideo")]
public class TVSerial
{
[Key]
public Int64 Video_ID { get; set; }
public string Series_Name { get; set; }
public string Season_No { get; set; }
public string Episode_No { get; set; }
public string Episode_Name { get; set; }
public string Time_Duration { get; set; }
public string File_Url_480p { get; set; }
public string File_Url_720p { get; set; }
public string Description { get; set; }
public bool Is_Active { get; set; }
public string Image_Url_Small { get; set; }
public string Image_Url_Big { get; set; }
}
public class TvSerialContext : DbContext
{
public DbSet<TVSerial> TvSerials { get; set; }
}
Here is controller class:
public class TvSerialController : Controller
{
public ActionResult ListAllTvSerial()
{
try
{
TvSerialContext tvContext = new TvSerialContext();
List<TVSerial> tv = tvContext.TvSerials.ToList();
return View(tv);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
}
Above code works as expected, but if i am doing this :
public ActionResult ListAllSeason(string serial)
{
try
{
TvSerialContext tvContext = new TvSerialContext();
List<TVSerial> tv = tvContext.TvSerials.Where(tvs => tvs.Series_Name == serial).Distinct().ToList();
return View(tv);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
it return all rows , i just want single row from every series_name and custom field "Series_Name,Season_No,Image_Url_Big"
i don't know how to achieve this.
getting result :
Expected result:-
You could do this by creating a view model and using a .GroupBy() clause
public class TVSerialVM
{
public string SeriesName { get; set; }
public string SeasonNo { get; set; }
public string ImageUrl { get; set; }
}
and the query to project into your view model
List<TVSerialVM> model = tvContext.TvSerials.Where(t => t.Series_Name == serial)
.GroupBy(t => new { t.Series_Name, t.Season_No, t.Image_Url_Big })
.Select(t => new TVSerialVM
{
SeriesName = t.Key.Series_Name,
SeasonNo = t.Key.Season_No,
ImageUrl = t.Key.Image_Url_Big
}).ToList();
Side note: Your duplicating data in the database (the season number and the image url). You should consider moving the image urls to another table with a relationship to the season number.
The reason you are getting multiple values even though you are using distinct is the Distinct method does not know what "equal" is for TVSerial.
You can use Distinct with IEqualityComparer.
https://msdn.microsoft.com/en-us/library/vstudio/bb338049(v=vs.100).aspx
Distinct is not guaranteed to on custom objects it doesn't know what to compare. I have used this SO in the past to make my custom object work with Distinct.
Creating a distinct list of custom type in C#
I have and entity framework project exposed via a data service:
public class VersionContext : DbContext
{
public DbSet<VersionTreeEntry> VersionTreeEntries { get; set; }
public DbSet<PluginState> PluginStates { get; set; }
public static void SetForUpdates()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<VersionContext, Configuration>());
}
}
public class VersionTreeEntry
{
public VersionTreeEntry()
{
Children = new List<VersionTreeEntry>();
PluginStates = new List<PluginState>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public virtual ICollection<VersionTreeEntry> Children { get; set; }
public virtual ICollection<PluginState> PluginStates { get; set; }
public virtual VersionTreeEntry Ancestor { get; set; }
/// <summary>
/// Links to the ProtoBufDataItem Id for the session state.
/// </summary>
public int DataId { get; set; }
public string Notes { get; set; }
[Required]
public DateTime TimeStamp { get; set; }
[MinLength(1, ErrorMessage = "Tag cannot have a zero length")]
[MaxLength(20, ErrorMessage = "A tag name cannot contain over 20 characters")]
public string Tag { get; set; }
public bool IsUiNodeExpanded { get; set; }
[Required]
public string Version { get; set; }
[Required]
public string SessionName { get; set; }
}
public class PluginState
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string PluginName { get; set; }
[Required]
public byte[] Data { get; set; }
}
As far as I can see, the data classes are defined correctly. I try to create some new objects and add them into the context, with their relations intact:
var session = new Session();
session.SessionName = "My new session";
VersionTreeEntry versionTreeEntry = new VersionTreeEntry();
versionTreeEntry.SessionName = session.SessionName;
versionTreeEntry.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
versionTreeEntry.TimeStamp = DateTime.Now;
_versionContext.AddToVersionTreeEntries(versionTreeEntry);
foreach (var plugin in session.Plugins)
{
using (var ms = new MemoryStream())
{
plugin.SaveState(ms);
PluginState state = new PluginState();
state.PluginName = plugin.PluginName;
state.Data = ms.ToArray();
versionTreeEntry.PluginStates.Add(state);
}
}
_versionContext.SaveChanges();
The problem is that the PluginState instances never actually get added to the database. If I add code to add them manually to the context, they do get added, but the foreign key pointing back to the VersionTreeEntry is null.
Again, this is a WCF DataService rather than vanilla EF, any idea what might be wrong?
Cheers
Posting the answer here from the comment section.
Agreed. The best way to do this is to call the following API:
_versionContext.AddRelatedObject(versionTreeEntry, "PluginStates", state);
Thanks
Pratik
We are using EF5, Code First approach to an MVC4 app that we're building. We are trying to update 1 property on an entity but keep getting errors. Here's what the class looks like which the context created:
public partial class Room
{
public Room()
{
this.Address = new HashSet<Address>();
}
public int RoomID { get; set; }
public Nullable<int> AddressID { get; set; }
public Nullable<int> ProductVersionID { get; set; }
public string PhoneNumber { get; set; }
public string AltPhone { get; set; }
public string RoomName { get; set; }
public string Description { get; set; }
public string Comments { get; set; }
public string Notes { get; set; }
public virtual ICollection<Address> Address { get; set; }
}
Here's our ViewModel for the view:
public class RoomDetailsViewModel
{
//public int RoomID { get; set; }
public string RoomName { get; set; }
public string PhoneNumber { get; set; }
public string AltPhone { get; set; }
public string Notes { get; set; }
public string StateCode { get; set; }
public string CountryName { get; set; }
public string ProductVersion { get; set; }
public int PVersionID { get; set; }
public List<SelectListItem> ProductVersions { get; set; }
public Room Room { get; set; }
}
Here's the Controller Action being called on "Save":
[HttpPost]
public virtual ActionResult UpdateRoom(RoomDetailsViewModel model)
{
var db = new DBContext();
bool b = ModelState.IsValid;
var rooms = db.Rooms;
var rm = rooms.Where(r => r.RoomID == model.Room.RoomID).Single();
//List<Address> address = db.Addresses.Where(a => a.AddressID == rm.AddressID).ToList<Address>();
rm.ProductVersionID = model.PVersionID;
//rm.Address = address;
db.Entry(rm).Property(r => r.ProductVersionID).IsModified = true;
//db.Entry(rm).State = System.Data.EntityState.Modified;
db.SaveChanges();
return View("RoomSaved", model);
}
All this view does is display data and allow the user to change the Product Version (from a SelectList), so, in the Room Entity, all we are updating is the ProductVersionID property, nothing else. We can get the data to display properly but when we click "save", we get this error:
An object of type 'System.Collections.Generic.List`1[[Models.Address,
Web.Mobile.TestSite, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]]' cannot be set or removed from the Value
property of an EntityReference of type 'Models.Address'.
As you can see by the Controller Action, we've tried several different things but all seem to produce this error. I've tried to populate the model.Room.Address collection with an Address, without, but still get this error.
I read this StackOverflow article and this article as well but neither have solved my problem.
ANY help with this would be greatly appreciated!
After hours and hours of digging, turns out that EF did not import some of the PK's for my DB tables. What tipped me off to this was on the Room class, the PK RoomID did not have the [Key] attribute on it. I tried to reimport the table through the edmx but it never came through as a key (even though it's clearly marked PK in the DB). So, to get around it, I created a partial class of my DBContext and override the OnModelCreating event and included the key, like so:
public partial class DBContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Models.Room>().HasEntitySetName("Rooms");
modelBuilder.Entity<Models.Room>().HasKey(r => r.RoomID);
}
}
Once this was done, the Action saved the record as hoped.
I hope this helps someone else!