Is it possible to read and write to a SQL Server database using DataTable with Entity Framework?
I have multiple code tables defined in my database such that each of them share a fixed set of properties as shown in the sample below.
For example
public class CTGender
{
public Guid ID { get; set; }
public string Description { get; set; }
public string DisplayValue { get; set; }
//...Other properties specific to CTGender
}
public class CTNationality
{
public Guid ID { get; set; }
public string Description { get; set; }
public string DisplayValue { get; set; }
//...Other properties specific to CTNationality
}
The situation I face right now is the ever expansion of my code tables, could be another CTCountry, CTRole and so on, for example.
I am trying to synchronise these code tables between multiple databases.
The solution is heavily dependent on Entity Framework as the data access.
Is there a generic way for Entity Framework to read and write ALL these code tables without their entity models defined, like how you can read and write generic DataTables using ADO.NET?
Yes, there are couple of ways by which you can create tables at code side then either using code first approach or using publish project mechanism you can generate tables in SQL server using entity framework.
In the latter approach, you can create a separate project where you can write SQL for your various tables. This project should target SQL Server. You can right click on this project and click on publish option for updating all your tables inside SQL server.
I have a simple code in Entity Framework (EF) v4.1 code first:
PasmISOContext db = new PasmISOContext();
var user = new User();
user.CreationDate = DateTime.Now;
user.LastActivityDate = DateTime.Now;
user.LastLoginDate = DateTime.Now;
db.Users.Add(user);
db.SaveChanges();
user.Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") };
db.SaveChanges();
db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") } });
db.SaveChanges();
The problem is that I get an error
An error occurred while saving entities that do not expose foreign key
properties for their relationships. The EntityEntries property will
return null because a single entity cannot be identified as the source
of the exception. Handling of exceptions while saving can be made
easier by exposing foreign key properties in your entity types. See
the InnerException for details.
at
db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") } });
db.SaveChanges();
I don't understand why the similar operation works. Is there something wrong with my model, or with ef-code-first?
public class Avatar
{
[Key]
public int Id { get; set; }
[Required]
public string LinkInString { get; set; }
[NotMapped]
public Uri Link
{
get { return new Uri(LinkInString); }
set { LinkInString = value.AbsoluteUri; }
}
}
public class User
{
[Key]
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public Avatar Avatar { get; set; }
public virtual ICollection<Question> Questions { get; set; }
public virtual ICollection<Achievement> Achievements { get; set; }
public DateTime CreationDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastActivityDate { get; set; }
}
For those of you who would still have this error with all keys properly defined, have a look at your entities and make sure you don't leave a datetime field with a null value.
This error message can be thrown for any kind of reason. The 'InnerException' property (or its InnerException, or the InnerException of that, etc) contains the actual primary cause of the problem.
It would of course be useful to know something about where the problem occurred - which object(s) in the unit of work is causing the problem? The exception message would normally tell you in the 'EntityEntries' property, but in this case, for some reason, that can't be done. This diagnostic complication - of the 'EntityEntries' property being empty - is apparently because some Entities 'do not expose foreign key properties for their relationships.'
Even if the OP gets the error because of failing to initialize DateTimes for the second instance of User, they get the diagnostic complication - 'EntityEntries' being empty, and a confusing top-level message ... because one of their Entity's doesn't 'expose foreign key properties'. To fix this, Avatar should have a public virtual ICollection<User> Users { get; set; } property defined.
The issue was resolved by adding an FK property.
In my case the following situation was giving me the same Exception:
Imagine a code first EF model where you have a Garage entity that has a collection of Car entities. I needed to remove a car from the garage so I ended up with code that looked like this:
garageEntity.Cars.Remove(carEntity);
Instead, it should've been looked like this:
context.Cars.Remove(carEntity);
Just for others who might have similar problems. I had the same error, but for a different reason. In one of the child objects I defined the [Key] as being a value which was the same for different saves. A stupid mistake on my part, but the error message does not instantly lead you to the problem.
In my case the exeception was thrown because EF had created a migration incorrectly.
It missed setting the identity: true on the second table. So go into the migrations which created the relevant tables and check if it missed to add identity.
CreateTable(
"dbo.LogEmailAddressStats",
c => new
{
Id = c.Int(nullable: false, identity: true),
EmailAddress = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.LogEmailAddressStatsFails",
c => new
{
Id = c.Int(nullable: false), // EF missed to set identity: true!!
Timestamp = c.DateTime(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.LogEmailAddressStats", t => t.Id)
.Index(t => t.Id);
An Id column should have identity (i.e. auto-incrementing!) so this must be a EF bug.
You could add identity manually with SQL directly to the database but I prefer using Entity Framework.
If you run in to the same problem I see two easy solutions:
Alt 1
reverse the incorrectly created migration with
update-database -target:{insert the name of the previous migration}
Then add the identity: true manually to the migration code and then update-database again.
Alt 2
you create a new migration that adds identity. If you have no changes in the models and you run
add-migration identity_fix
it will create an empty migration. Then just add this
public partial class identity_fix : DbMigration
{
public override void Up()
{
AlterColumn("dbo.LogEmailAddressStatsFails", "Id", c => c.Int(nullable: false, identity: true));
}
public override void Down()
{
AlterColumn("dbo.LogEmailAddressStatsFails", "Id", c => c.Int(nullable: false));
}
}
This problem can also arise from reversed key declarations. If you're using fluent to configure the relationship, make sure the left and right keys are mapped to the correct entity.
I hade same probleme. in my case, it was due to datetime field with a null value. I had to passe a value to datetime and evrythings went fine
Another answer:
I used this:
public List<EdiSegment> EdiSegments { get; set; }
instead of this:
public virtual ICollection<EdiSegment> EdiSegments { get; set; }
and got the error message noted above.
I had the same error and in my case the problem was that I added a relationship object which had already been loaded "AsNoTracking". I had to reload the relation property.
BTW, Some suggest using "Attach" for relations that already exist in db, I haven't tried that option though.
In my case, the problem was that I renamed a column improperly, so the migration made two columns, one called "TeamId" and one called "TeamID". C# cares, SQL doesn't.
Yet another different case here.
A query was cast to a list and while doing that, it created entities by their constructor for comparison in the linq expression right after the ToList(). This created entities that gotten into the deleted state after the linq expression finished.
However! There was a small adjustment that created another entity in the constructor, so that this new entity got linked to an entity that was marked as Deleted.
Some code to illustrate:
query.Except(_context.MyEntitySetSet()
.Include(b => b.SomeEntity)
.Where(p => Condition)
.ToList() // This right here calls the constructor for the remaining entities after the where
.Where(p => p.Collection.First(b => Condition).Value == 0)
.ToList();
The constructor of MyEntity:
public partial class MyEntity
{
protected MyEntity()
{
// This makes the entities connected though, this instance of MyEntity will be deleted afterwards, the instance of MyEntityResult will not.
MyEntityResult = new MyEntityResult(this);
}
}
My solution was to make sure the entire expression was done inside the IQueryable so that there won't be any objects created.
I'm not entirely sure that it's going to help in your case because I'm setting up my tables using Fluent API, however, as far I can tell, the issue arises regardless whether the schema is set up using data annotations (attributes) or Fluent API (configuration).
There seems to be a bug in EF (v. 6.1.3) as it omits certain changes to the schema when updating the DB to the next migration. The quickest route around it is (during the development stage) to remove all the tables from the DB and runt migrations from init stage again.
If you're already in production, the quickest solution I've found was to manually change the schema in the DB or, if you want to have version control of the changes, manually manipulate the methods Up() and Down() in your migration.
Today I faced this issue and tried the possible solutions posted above but none of them helped me. I had UnitOfWork pattern implemented and system was committing the data in last after adding all the records.
In my case system was combining the two models and querying the DB
Invalid object name 'dbo.RoleModelUserModel'.
where these were two different models actually.
I fixed this by reordering the insert statements and adding the parent entity first. In this case added the user first and issue resolved.
After a bit of investigation I found that whilst .Net supports a minimum date (DateTime.MinValue) of 01/01/0001 00:00:00 and a maximum (DateTime.MaxValue) of 31/12/9999 23:59:59 in SQL Server Compact Edition minimum date is 01/01/1753 00:00:00.
When I entered a date greater than 01/01/1753 00:00:00, this error disappeared.
Is your application or website being accessed from some third party application when this error is coming? If yes, then please check the access rights of the account which is sending the request to your application.
In our case, it was ServiceNow MID server service which was the culprit. It is a Windows service. If you want to know more about it then please read this link. So basically, you need to check two things:
Under the context of which account the calling service should run to access your application?
What all access rights are needed for the service's log on account to do all allowed operations in your application?
As per this article of ServiceNow we had to give Log on as a service right to the MID Server service's log on account. You can do it via in Local Security Policies console (Refer screenshot).
After we gave the proper access rights to the logon account, the Entity Framework issue went away. Please remember that the access rights and the log on account to be used will be specific to your application.
I'm playing around trying to get a simple MVC website working. In it I am using a database and Entity Framework to communicate with it (as I have been doing for months on other projects).
Everything has been going fine up until I tried to retrieve from a specific table in my database. If I query that, the select that EF generates mysteriously contains a column that does not exists in that table (or any table in that database). This of course throws an exception complaining about the column not existing:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'PerformerFolder_Id'.
I've created a UnitOfWork object that uses the repository pattern to retrieve the data, and to make it as simple as possible, I exposed the DataContext so I could manually query that for testing:
var test = loUnitOfWork.Context.Set<DAL.File>();
The DAL.File is a class generated by the POCO generator:
public partial class File : BaseEntity
{
public int Id { get; set; }
public string FilePath { get; set; }
public string FileName { get; set; }
public virtual ICollection<FilePerformer> FilePerformerCollection { get; set; }
public virtual ICollection<FileProperty> FilePropertyCollection { get; set; }
public File()
{
FilePerformerCollection = new List<FilePerformer>();
FilePropertyCollection = new List<FileProperty>();
InitializePartial();
}
partial void InitializePartial();
}
I do have a PerformerFolder that has an Id column as the primary key, but that is in no way connected to the file table.
If I enable debug logging on the DataContext I see that it runs the following query:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FilePath] AS [FilePath],
[Extent1].[FileName] AS [FileName],
[Extent1].[PerformerFolder_Id] AS [PerformerFolder_Id]
FROM [dbo].[File] AS [Extent1]
I've tried searching all file for "PerformerFolder" and other than the logical places (in the PerformerFolder class) it did not turn up anything. It seems to be generated based on something, but I just can't figure out what or where.
Does anyone have any suggestions?
Try searching all code files for PerformerFolder without the 'id'
EF adds that to navigation properties on it's own.
as #Giorgi mentioned, it must be a partial class somewhere, or maybe a left over from a previous build ?
after carefully researching for a solution to this strange problem that I have and accomplished nothing. I am pretty much desperated.
I am working on a MVC3 project.
I have a DB Context class like this:
//SpaceUpEntities.cs
public class SpaceUpEntities: DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Profile> Profiles { get; set; }
public DbSet<Venue> Venues { get; set; }
public DbSet<Room> Rooms { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<Capacity> Capacities { get; set; }
public DbSet<VenueStatus> VenueStatuses { get; set; }
}
and I initialize DBContext when application start
//Global.asax.cs
protected void Application_Start()
{
Database.SetInitializer<SpaceUpEntities>(null);
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
RegisterDependencyInjection();
ModelBinders.Binders.DefaultBinder = new TrimModelBinder();
}
The problem occurs when I want to query/Insert/Update to the DB.
For example this piece of code
//SecurityRepository.cs
public RegisterFeedback Register(User user, Profile profile)
{
try
{
using (var entities = new SpaceUpEntities())
{
// Check existing email address
var emailExisted = entities.Users.FirstOrDefault(i => i.Email == user.Email);
//... So on
}
}
catch (Exception e)
{
Logger.Error(e);
return new RegisterFeedback(false, Messages.GeneralError);
}
}
After using (var entities = new SpaceUpEntities()) entities should have been initialized but I ended up with this error
Error Message:
Function evaluation disabled because a previous function evaluation
timed out. You must continue execution to reenable function
evaluation.
Initially, I thought it was a connection problem to my server, so I checked:
ConnectionString
SQL Server setting (SQL Server 2012)
Although I can hardly see why they are the cause of this problem since I took serveral methods to test my ConnectionString to find it has no issue.
Any help would certainly be appreciated.
Thank you in advance.
Thang Do
P/S: this is how I tested my connection string:
This is my connection string
I tested it with this
Make sure you are using the Initialization strategy which matches what you are trying to achieve. Database.SetInitializer<T>(...);
By having the line below in your App_Start method, I believe you may be bypassing initialization
Database.SetInitializer<SpaceUpEntities>(null);
Here are some options from an article on code first database initialization strategies that I hope will be helpful to you:
There are four different database Initialization strategies:
CreateDatabaseIfNotExists: This is default initializer. As name suggests, it will create the database if none exists as per the configuration. However, if you change the model class and then run the application with this initializer, then it will throw an exception.
DropCreateDatabaseIfModelChanges: This initializer drops an existing database and creates a new database, if your model classes (entity classes) have been changed. So you don’t have to worry about maintaining your database schema, when your model classes change.
DropCreateDatabaseAlways: As the name suggests, this initializer drops an existing database every time you run the application, irrespective of whether your model classes have changed or not. This will be useful, when you want fresh database, every time you run the application, while you are developing the application.
Custom DB Initializer: You can also create your own custom initializer, if any of the above don't satisfy your requirements or you want to do some other process that initializes the database using above initializer
I'm having a very odd issue with SubSonic where when I edit a class the database isn't being updated, even when I delete it and regenerate it.
Example: Simple class
public class Customer {
public Guid Id { get; set; }
public string Description { get; set; }
}
Customer c = new Customer() { Id = Guid.NewGuid(), Description = "Toaster" };
var repo = new SimpleRepository("CustomerTest",
SimpleRepositoryOptions.RunMigrations);
repo.Add(c);
If I run this code it works perfectly, creates a table "Customer" and inserts the row for the toaster. However if I decide to change my Customer class to:
public class Customer {
public Guid Id { get; set; }
public string Description { get; set; }
public int Cost { get; set;}
}
And run the same code adding a value for the Cost property the database table remains "Id, Description". If I create a totally new class and past in the Customer fields it will create the table correctly the first time and again any changes dont appear to work.
Any help?
First off all, you should try to figure out if subsonic detects your class definition changes properly.
This code should give you a overview of the statements subsonic want's to execute.
var migrator=new SubSonic.Schema.Migrator(Assembly.GetExecutingAssembly());
var provider=ProviderFactory.GetProvider("CustomerTest");
string[] commands=migrator.MigrateFromModel<Customer>(provider);
commands should contain all changes subsonic wants to make to your database.
You can execute these commands by yourself with:
BatchQuery query = new BatchQuery(provider);
foreach(var s in commands)
query.QueueForTransaction(new QueryCommand(s.Trim(), provider));
//pop the transaction
query.ExecuteTransaction();
(code taken from http://subsonicproject.com/docs/3.0_Migrations).
That said, I suppose commands will be empty in your case.
In that case that could be caused by a statement that is not implemented by the provider you are using (SqlServer/MySQL/SQLite/Oracle). Maybe you should download the SubSonic source and step into the migrator.MigrateFromModel(...) method to see what happens.
Another possible cause (if you use MySQL) could be that your information schema is not up to date. I encountered this problem a while ago. After changing my database and regenerating the DAL with SubSonic 2, my generated code didn't change.
I figured out that the mysql information schema (and subsonic does queries on the information schema) hadn't changed yet.
I solved this by executing FLUSH TABLES which caused the information scheme to reload. I don't know if that's a bug in mysql or desired behaviour but you should try FLUSH TABLES first.