I have set up my first project using FluentNHibernate. When I tried to get a list of records from a single table, I got an exception which says:
System.FormatException : String was not recognized as a valid Boolean.
The problem is that in the database table, there is a column called "flag" and its data type is char, but it only contains values of either '0' or '1'. So, I'd like to map it to type bool in my POCO:
public class Students
{
public virtual int Id {get; private set;}
public virtual string FirstName {get; set;}
public virtual string LastName {get; set;}
public virtual DateTime RegisterDate {get; set;}
public virtual bool Flag {get; set;}
}
Now, in my Mappings.cs, how do I convert Flag to bool?
public class StudentMap : ClassMap<Students> {
public StudentMap() {
Id(x => x.Id);
Map(x => x.FirstName).Column("first_name");
Map(x => x.LastName).Column("last_name");
Map(x => x.RegisterDate).Column("register_date");
Map(x => x.Flag); // This won't work because
// column "flag" is char,
// whereas x.Flag is bool.
}
}
That's question 1.
Also, in the database, the table name is "students", but in my business model, I want to use the singular as Student, how can I do this? Right now, if I define my business class as Student, I will get an error which says something like the table "student" is not found.
The database is MySQL, if that matters.
Thanks for your hint.
For part 1, use this on your app.config/nhibernate.config/whateverYourNHibernateConfigFile
<property name="query.substitutions">true 1, false 0</property>
Edit after comment:
If you're using fluent nhibernate, just uses its API, example
var props = new Dictionary<string, string>();
props.Add("query.substitutions","true 1, false 0");
var sessionFactory = Fluently.Configure().BuildConfiguration().AddProperties(props);
For part 1, in your configuration object, you need to set the query.substitutions property to true=1, false=0.
For part 2, there should be a Table("") method you can use to specify the table name in the StudentMap class.
Related
Assume I've read and googled, and I still don't know what I'm doing incorrectly. Whenever I try to execute
_dbContext.Set<T>().Add(aMediaObjectWithAssociatedProvider);
_dbContext.SaveChanges();
I get the dreaded efcore violation of primary key constraint reference table
I have a class as such:
public class Media : BaseModel
{
public virtual string Title { get; set; }
public virtual string? Description { get; set; }
public virtual string Source { get; set; }
public virtual Guid? MediaTypeId { get; set; }
public virtual Guid? ProviderId { get; set; }
public virtual DateTime? StartDate { get; set; }
public virtual DateTime? EndDate { get; set; }
public virtual Provider? Provider { get; set; }
}
The BaseModel class is
public abstract class BaseModel : IBaseModel
{
public virtual Guid Id { get; set; }
}
The Provider class is as such:
public class Provider : BaseModel
{
public virtual string Name { get; set; }
public virtual string? ApiUsername { get; set; }
public virtual string? ConfigurationSection{ get; set; }
}
My DBContext has the following:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Media>().HasKey(x => x.Id);
mb.Entity<Media>().HasOne(p => p.Provider).WithOne().HasForeignKey<Media>(x => x.ProviderId);
}
The code for inserting a new object is as follows:
public T Insert(T oneObject)
{
try
{
// Ensure the entity has an ID
if (oneObject.Id == Guid.Empty)
{
oneObject.Id = Guid.NewGuid();
}
_dbContext.Set<T>().Add(oneObject);
_dbContext.SaveChanges();
}
catch (Exception error)
{
_logger.LogError(error.Message, error);
}
return oneObject;
}
Assume that providers are static, in a sense that they already exist in their table, and I don't want to add new providers when I save media... Media just needs to have a provider.
I know exactly what is happening (the model, after travelling through json back through the api to the server is losing context, but I'm also trying to build a repository type of system where I don't have to build complex save logic for every object. (hence why i'm hand wringing over adding code that loads existing providers).
This problem specifically began rearing its head when I was saving new Media objects into the database with existing Providers. I am still mulling over how to look up children dynamically, but i'm not quite there yet.
I've been at this for so long, i'm about ready to give up on efcore relations and just rebuild the models as single objects, and handle all of the manipulation in javascript. And I don't like this idea.
I know for a fact that there will be questions for more code, but please let me know what. Again, I'm just stepping into .net core / ef core so this code-first is a little confusing for me. Thanks
You may have 2 options to try. Do backup your whole project and database beforehand. Clone your database to another database name. Try these either one option using new cloned database for testing.
No.1
Set "newid()" without quotes in your ID's default value in sql server. So you don't need to use Guid.NewGuid() in code every insert. newid() will auto generate GUID.
No. 2
How about removing primary key from ID (GUID) and then creating new column "UID" (running number) and set UID (running number) as primary key and enable its identity? You need to change all other tables too. And re-link UID each other if you use relationship. This way, your UID will not have existing number when insert.
I have the following model:
public class TestModel
{
public byte[] File { get; set; }
}
which maps File to a varbinary(max) column in SQL Server.
Now I want to get file length without loading the data. I can do that by
context.Test.Select(x => SqlFunctions.DataLength(x.File)).ToList();
How can I extend my model to have FileLength in it as an automatically calculated field in it? Eg something like
public class TestModel
{
public byte[] File { get; set; }
[MapToDBFunction(SqlFunctions.DataLength)] <== WHAT SHOULD BE HERE??
public int? FileLength { get; set; }
}
Not in the entity, the code to calculate it could only determine that by first loading it. I believe a solution that would suit your needs is to bind that entity to a view rather than a table. The view can then have a computed column for the file length.
I have annotated some of my model classes' keys with [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
and added a migration.
When running Update-Database I keep getting following error message:
To change the IDENTITY property of a column, the column needs to be dropped and recreated.
I also tried to Update-Database with a complete new database, to no avail as the error is the same.
When changing the identity property in SQL Server Management Studio, I do not get such error but I would like to avoid a mix of code and DB first approach.
Is there a way to either
force the update to drop and recreate the column
or drop and recreate the table ?
EDIT1:
To answer a question from the comments. My model class before looked like:
public partial class MyModel
{
[Key]
public int Id { get; set; }
[MaxLength(70)]
public string Name { get; set; }
public string Description { get; set; }
...
}
This is my model class after adding the annotation:
public partial class MyModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(70)]
public string Name { get; set; }
public string Description { get; set; }
...
}
Is there an option to have dapper throw an error if the Query method fails to find a property matching a returned column in a result set?
For example:
public class Person{
public String FirstName {get; set;}
public String LastName {get; set;}
}
...
conn.Query<Person>("select FName, LName from Users");
The above would throw no error despite that no data was transferred due to the name mismatch.
If not is there a reason not to add it? My old home-grown micro-ORM did this and I miss the feature so I'd consider attempting to add it, but not if there were specific design decisions that already eliminated it (ie "raw performance").
I ended up using a chunk of code called SafeDapper:
https://github.com/LarrySmith-1437/SafeDapper
Different naming property you must be manual mapping.
Install Dapper.FluentMap NuGet package.
Manual mapping
public class PersonMap : EntityMap<Person>
{
public PersonMap()
{
// Map property 'FirstName' to column 'FName'.
Map(p => p.FirstName)
.ToColumn("FName");
// Map property 'FirstName' to column 'FName'.
Map(p => p.LastName)
.ToColumn("LName");
}
}
Initialization:
FluentMapper.Initialize(config =>
{
config.AddMap(new PersonMap());
});
I want to create a model on MVC3, but instead of creating a model for a table, I want to create one for a view in my Database. I know that with models for tables, I need to specify primary keys when creating the model, if not i get some error messages. Since views do not have have primary/foreign keys, how do I go about creating models for View?
At any MVC application that works with EF you may have different models to create tables in db or conceptual model for view that doesn't create any tables.Table creation depends on what properties of which model classes you'll define in class that inherited from DbContext. Notice that any property that exists in this class and its relational classes will create table in db. So,to create models that will be used only at view, you can define models that don't have any relationship to other table creator models plus no definition at inherited DbContext class. Then you can use them as model or class to show data at the view.The controller and its related view should use the same model and no errors will be occurred.
public class datacontext : DbContext
{
public DbSet<Person> people { get; set;}
public DbSet<Address> address { get; set;}
}
public class Person
{
[Key]
public int ID { get; set;}
public String Name { get; set;}
}
public class Address
{
[Key]
public int ID { get; set;}
public Country country { get; set;}
public String Details { get; set;}
}
public class Country
{
[Key]
public int ID { get; set;}
public String Name { get; set;}
}
public class Work_Field//without any key definition
{
public String Title { get; set;}
public String Description { get; set;}
}
Here we have this tables : Person, Address, Country(Although it's not defined at datacontext class)
In this example, you can use Work_Field as view model perhaps with some DataAnnotations like [Required],... to force user don't leave parameter empty, and so more.