I need your help on this. I always get the error "Invalid column name 'Discriminator'" every time I do a select. What's weird is that, I don't have any Discriminator column in my mapping or in my table. I tried adding the [NotMapped] in my class (as mentioned here: EF Code First “Invalid column name 'Discriminator'” but no inheritance) but to no avail.
Below are my codes which triggered the error.
Model
public class MasterUser : IAuditFields
{
[Key]
public string Username { get; set; }
public string Name { get; set; }
public string GroupID { get; set; }
public string Status { get; set; }
public string DeptID { get; set; }
public string Rank { get; set; }
public string CreatedBy { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
public string LastModifiedBy { get; set; }
public DateTime? LastModifiedDate { get; set; }
#region Relationships
public UserAccess UserAccess { get; set; } // User needs to see what user access group he/she is in
public UserAccessDetail UserAccessDetail { get; set; } //User needs to see what he/she can do
#endregion
}
Interface
public interface IAuditFields
{
string CreatedBy { get; set; }
DateTime CreatedDate { get; set; }
string LastModifiedBy { get; set; }
DateTime? LastModifiedDate { get; set; }
}
Configuration class
public class MasterUserConfig : EntityTypeConfiguration<MasterUser>
{
public MasterUserConfig()
{
Property(usr => usr.Username)
.HasColumnName("UserName")
.IsRequired();
Property(usr => usr.Name).HasColumnName("Name");
Property(usr => usr.GroupID).HasColumnName("GroupId");
Property(usr => usr.Status).HasColumnName("Status");
Property(usr => usr.DeptID).HasColumnName("DeptId");
Property(usr => usr.Rank).HasColumnName("Rank");
Property(usr => usr.CreatedBy).HasColumnName("CreatedBy");
Property(usr => usr.CreatedDate).HasColumnName("CreatedDate");
Property(usr => usr.LastModifiedBy).HasColumnName("LastModifiedBy");
Property(usr => usr.LastModifiedDate).HasColumnName("LastModifiedDate");
ToTable("dbo.Users");
}
DataContext
public class BBDataContext : DbContext
{
public DbSet<MasterUser> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
try
{
modelBuilder.Configurations.Add(new MasterUserConfig());
base.OnModelCreating(modelBuilder);
}
catch (Exception ex)
{
DiagnosticHelper.Message = ex.Message;
DiagnosticHelper.InnerException = ex.InnerException.Message;
DiagnosticHelper.StackTrace = ex.StackTrace;
DiagnosticHelper.Instance.WriteError();
}
}
}
Select method
public MasterUser GetUserByUsername(string userName, string password)
{
try
{
return (_context.Users
.Where(usr => usr.Username == userName && usr.Password == password && usr.Status == "ACTIVE"))
.SingleOrDefault();
}
catch (Exception ex)
{
LogError(ex);
}
return null;
}
Hope you can help me. Thanks a lot!
I've had the same error under slightly different circumstances, I was using inheritance. The problem was fixed by ensuring that all tables/links that can be reached from the model class are configured by your context.
In your case this is the UserAccess and UserAccessDetail classes (and anything else that can be reached from them). Try configuring these in OnModelCreating.
Related
I have a model Template with List<Symbol> symbols, and an equivalent ViewModel TemplateJS with List<SymbolJS>. When I query for a Template, ProjectTo<TemplateJS> seems to throw an Exception and I'm not sure why.
Exception: "Argument types do not match"
I would also like to Include Symbol in my query but I'm not exactly sure how to map that object as well. Would this need be done in a separate query?
Any help is appreciated! Thanks!
Models :
public class Template
{
public int Id { get; set; }
public string Name { get; set; }
public List<Exercise> Exercises { get; set; }
public List<Symbol> Symbols { get; set; }
}
public class Symbol
{
public int Id { get; set; }
public int TemplateId { get; set; }
public Template Template { get; set; }
public char Letter { get; set; }
public string ImgSource { get; set; }
}
public class TemplateJS
{
public int Id { get; set; }
public string Name { get; set; }
public List<SymbolJS> Symbols { get; set; }
}
public class SymbolJS
{
public char Letter { get; set; }
public string ImgSrc { get; set; }
}
AutoMapper :
CreateMap<Template, TemplateJS>()
.ReverseMap();
CreateMap<Symbol, SymbolJS>()
.ReverseMap();
Query :
public async Task<TemplateJS> GetTemplateAsync(int Id)
{
try
{
var q = await _dbContext.Template
// .Include(x => x.Symbols)
.Where(x => x.Id == Id)
.ProjectTo<TemplateJS>(_mapper.ConfigurationProvider)
.SingleOrDefaultAsync();
return q;
}
catch (Exception e)
{
throw e;
}
}
I am trying to use fluent validation in ServiceStack. I've added the validation plugin and registered my validator.
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);
I have implemented a validator class for my service model:
public class CreateLeaveValidator : AbstractValidator<CreateLeave>
{
public CreateLeaveValidator()
{
RuleFor(cl => cl.StudentId).NotEmpty();
RuleFor(cl => cl.LeaveDepart).NotEmpty().GreaterThan(DateTime.Now).WithMessage("Leave must begin AFTER current time and date.");
RuleFor(cl => cl.LeaveReturn).NotEmpty().GreaterThan(cl => cl.LeaveDepart).WithMessage("Leave must end AFTER it begins.");
RuleFor(cl => cl.ApprovalStatus).Must( status => ( ("P".Equals(status)) || ("C".Equals(status)) || ("A".Equals(status)) || ("D".Equals(status)) ) );
}
}
Service Model:
[Route("/leaves", "POST")]
public class CreateLeave : IReturn<LeaveResponse>, IUpdateApprovalStatus
{
public int StudentId { get; set; }
public DateTime RequestDate { get; set; }
public DateTime LeaveDepart { get; set; }
public DateTime LeaveReturn { get; set; }
public string Destination { get; set; }
public string HostRelationship { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string Hostphone { get; set; }
public string Cellphone { get; set; }
public string Transport { get; set; }
public string Driver { get; set; }
public string Companions { get; set; }
public string Reason { get; set; }
public string ApprovalStatus { get; set; }
public DateTime ApprovalDate { get; set; }
public string ApprovalComment { get; set; }
public string ApprovalReason { get; set; }
public int ApprovalUser { get; set; }
}
But when I create a request with no StudentId or an invalid ApprovalStatus, the validator does not appear to fire and catch the invalid request.
How can I go about troubleshooting the cause of this?
UPDATE: Correction it appears validators are working with my actual service but not in my unit tests. I'm guessing I must not be configuring my apphost correctly in the unit test setup. Here's my test constructor:
public LeaveTests()
{
Licensing.RegisterLicense(#"[license key]");
appHost = new BasicAppHost(typeof(ApiServices).Assembly).Init();
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
appHost.Plugins.Add(new ValidationFeature());
appHost.Container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);
}
ServiceStack Validation filters are executed in a Global Request Filter which require a full integration test to run, e.g:
public class MyIntegrationTests
{
ServiceStackHost appHost;
public MyIntegrationTests()
{
appHost = new AppHost()
.Init()
.Start("http://localhost:8000/");
}
[OneTimeTearDown] void OneTimeTearDown() => appHost.Dispose();
[Test]
public void Execute_validation_filters()
{
var client = new JsonServiceClient("http://localhost:8000/");
try
{
var response = client.Post(new CreateLeave { ... });
}
catch(WebServiceException ex)
{
//...
}
}
}
I have working solution, but a bit doubt if I made it correctly. I have base class from which derive 3 other classes Ad:
public class Ad
{
public int Id { get; set; }
public string Title { get; set; }
public Address Address { get; set; }
}
My Address class look like this:
public class Address
{
[ForeignKey("Ad")]
public int AddressId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public virtual Ad Ad { get; set; }
}
Now I'm using automapper with this mapping:
Mapper.Initialize(config =>
{
config.CreateMap<Auto, AutoViewModel>()
.ForMember(m => m.City, vm => vm.MapFrom(m => m.Address.City))
.ForMember(m => m.Street, vm => vm.MapFrom(m => m.Address.Street))
.ForMember(m => m.ZipCode, vm => vm.MapFrom(m => m.Address.ZipCode)).ReverseMap();
});
Where AutoViewModel looks like this:
public class AutoViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
In my Create and Edit actions I use this binding:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, AutoViewModel vm)
{
Address address = new Address();
address.AddressId = vm.Id;
address.City = vm.City;
address.Street = vm.Street;
address.ZipCode = vm.ZipCode;
var auto = Mapper.Map<Auto>(vm);
auto.Address = address;
if (id != auto.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(auto);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AutoExists(auto.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(auto);
}
Is this way correct? Is there elegant way to do it? I had to specify AddressId explicit because otherwise I'm getting duplicate Foreign key error message...
I have the following entities in my solution
public class UtilityAccount : IObjectWithState
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid UtilityAccountID { get; set; }
public string Account { get; set; }
[ForeignKey("Person")]
public Guid PersonID { get; set; }
public virtual Person Person { get; set; }
public string ForeignID { get; set; }
[NotMapped]
public ObjectState ObjectState { get; set; }
public virtual ICollection<Utility> Utilities { get; set; }
public UtilityAccount()
{
Utilities = new List<Utility>();
}
}
public class Utility : IObjectWithState
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid UtilityID { get; set; }
[ForeignKey("UtilityAccount")]
public Guid UtilityAccountID { get; set; }
public virtual UtilityAccount UtilityAccount { get; set; }
public Guid? ServiceAddressID { get; set; }
[ForeignKey("ServiceAddressID")]
public virtual Address ServiceAddress { get; set; }
[NotMapped]
public ObjectState ObjectState { get; set; }
public double CurrentBalance { get; set; }
public double? PendingPaymentTotal { get; set; }
public string ForeignID { get; set; }
[ForeignKey("UtilityType")]
public Guid UtilityTypeID { get; set; }
public virtual UtilityType UtilityType { get; set; }
public virtual ICollection<UtilityBill> UtilityBills { get; set; }
public virtual ICollection<IncomingUtilityPayment> IncomingPayments { get; set; }
public Utility()
{
UtilityBills = new List<UtilityBill>();
IncomingPayments = new List<IncomingUtilityPayment>();
}
}
public class IncomingUtilityPayment : IObjectWithState
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid IncomingPaymentID { get; set; }
public string ForeignID { get; set; }
[ForeignKey("Utility")]
public Guid UtilityID { get; set; }
public virtual Utility Utility { get; set; }
public DateTime PaymentDate { get; set; }
public IncomingPaymentStatus IncomingPaymentStatus { get; set; }
public double? UtilityAmount { get; set; }
public double? ConvenienceFee { get; set; }
public double? TotalAmount { get; set; }
public string AuthCode { get; set; }
public string AuthReference { get; set; }
public string TenderType { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PaymentIdent { get; set; }
[NotMapped]
public ObjectState ObjectState { get; set; }
}
My problem is that I am trying to use Linq to retrieve information about a UtilityAccount and I am running into issues with the IncomingPayments for a Utility. Below is the select statement I am trying to use.
returnVal = repo.AllIncluding(o => o.Person, o => o.Utilities, o => o.Utilities.Select(p => p.UtilityType), o => o.Person.BillingAddress, o => o.Utilities.Select(p => p.ServiceAddress), o => o.Utilities.Select(p => p.IncomingPayments.Where(q => q.IncomingPaymentStatus == IncomingPaymentStatus.Pending || q.IncomingPaymentStatus == IncomingPaymentStatus.Processed )));
Everything ran fine until I added this clause to the statement.
o => o.Utilities.Select(p => p.IncomingPayments.Where(q => q.IncomingPaymentStatus == IncomingPaymentStatus.Pending || q.IncomingPaymentStatus == IncomingPaymentStatus.Processed ))
I think my issue ends up being something I am writing wrong in my Linq clause. The error I am getting is
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
Parameter name: path
I can use the following statement with no issues
o => o.Utilities.Select(p => p.IncomingPayments)
as soon as I add the where clause in I get the error
I'm not familiar with EntityFramework nor linq-to-entities, but if it's just like linq-to-object you can:
add a .Where(p => p.IncomingPayments != null) before chaining with your .Select() like this
o.Utilities.Where(p => p.IncomingPayments != null)
.Select(p => p.IncomingPayments.Where(q => q.IncomingPaymentStatus == IncomingPaymentStatus.Pending || q.IncomingPaymentStatus == IncomingPaymentStatus.Processed))
The result will be a nested IEnumerable, i.e. IEnumerable<IEnumerable<IncomingUtilityPayment>>
If you actually need a IEnumerable<IncomingUtilityPayment> then .SelectMany() come in to play.
o.Utilities.Where(p => p.IncomingPayments != null)
.SelectMany(p => p.IncomingPayments)
.Where(q => q.IncomingPaymentStatus == IncomingPaymentStatus.Pending || q.IncomingPaymentStatus == IncomingPaymentStatus.Processed)
Hope this help
I am working on a project in ASP.NET MVC using EF4 Code-First for the modeling. I have the following model classes:
public class ComicBook
{
public long ComicBookID { get; set; }
public string IssueTitle { get; set; }
public int IssueNumber { get; set; }
public DateTime PublishDate { get; set; }
public IList<ComicBookPerson> Writers { get; set; }
public IList<ComicBookPerson> Pencillers { get; set; }
public IList<User> CollectingUsers { get; set; }
}
public class ComicBookPerson
{
public long ComicBookPersonID { get; set; }
public string Name { get; set; }
public IList<ComicBook> WorkedOnComicBooks { get; set; }
}
public class User
{
[Key]
public long UserID { get; set; }
public string Email { get; set; }
public IList<ComicBook> CollectedBooks { get; set; }
}
And the following DbContext:
public class ComicContext : DbContext
{
public DbSet<ComicBook> ComicBooks { get; set; }
public DbSet<ComicBookPerson> ComicBookPerson { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ComicBook>()
.HasMany(b => b.Writers)
.WithMany(w => w.WorkedOnComicBooks)
.Map(t => t.MapLeftKey("ComicBookID")
.MapRightKey("WriterID")
.ToTable("ComicBook_Writers"));
modelBuilder.Entity<ComicBook>()
.HasMany(b => b.Pencillers)
.WithMany(p => p.WorkedOnComicBooks)
.Map(t => t.MapLeftKey("ComicBookID")
.MapRightKey("PencillerID")
.ToTable("ComicBook_Penciller"));
}
}
The rules that need to apply are:
Users can have many ComicBooks in their collection
ComicBooks can be in many users' collections
Each ComicBook can have 1 or more Writers
Each ComicBook can have 1 or more Pencillers
A ComicBookPerson can be a Writer or a Penciller on any book
A ComicBookPerson can work on many books, as a Writer, Penciller, or both
The many-to-many schema between Users and ComicBooks is created fine. It is the many-to-many between ComicBooks and ComicBookPersons that is breaking. The error message I get is:
Schema specified is not valid. Errors:
(15,6) : error 0040: Type ComicBook_Writers is not defined in namespace Comics.Models (Alias=Self).
I basically want two join tables, one called ComicBook_Writers and one called ComicBookPencillers. Both tables will contain a ComicBookID and a ComicBookPersonID. Is this possible in EF Code First?
You need two collection properties in ComicBookPerson class that relates to writers and pencillers.
public class ComicBookPerson
{
public long ComicBookPersonID { get; set; }
public string Name { get; set; }
public IList<ComicBook> WroteComicBooks { get; set; }
public IList<ComicBook> PenciledComicBooks { get; set; }
}
Model mapped as
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ComicBook>()
.HasMany(b => b.Writers)
.WithMany(w => w.WroteComicBooks)
.Map(t => t.MapLeftKey("ComicBookID")
.MapRightKey("WriterID")
.ToTable("ComicBook_Writers"));
modelBuilder.Entity<ComicBook>()
.HasMany(b => b.Pencillers)
.WithMany(p => p.PenciledComicBooks)
.Map(t => t.MapLeftKey("ComicBookID")
.MapRightKey("PencillerID")
.ToTable("ComicBook_Penciller"));
}
I think this model is close to be right, but still missing something.
The ComicBookPerson can be both writer and penciller, that means you still need a third list in your class ComicBookPerson:
public IList<ComicBook> WroteComicBooks { get; set; }
public IList<ComicBook> PenciledComicBooks { get; set; }
public IList<ComicBook> WrotPencComicBooks { get; set; }
Am I right?