Servicestack Ormlite multi-column constraint fails where constraint includes Enum - enums

I am using ServiceStack.Ormlite, and also make heavy use of the automatic handling of enums whereby they are stored in the db as strings but retrieved and parsed nicely back into Enums on retrieval, so I can do easy type-comparison - say, for a property "UserRole" in the db/table class "User" of enum type "UserRoleEnum" (just for demonstration).
This works great.. until I want to use the enum property to define a multi-column unique constraint
CompositeIndexAttribute(bool unique, params string[] fieldNames);
like:
[CompositeIndex(true, nameof(UserId), nameof(UserRole)]
public class User
{
public long UserId {get;set;}
public UserRoleEnum UserRole {get;set;
}
(as per :
How to Create Unique Constraint with Multiple Columns using ServiceStack.OrmLite? ).
At which time i get:
System.Data.SqlClient.SqlException
Column 'UserRole' in table 'User' is of a type that is invalid for use as a key column in an index.
I currently see options as:
a) Define UserRole as a string (isntead of UserRoleEnum ) in the table entity class and lose the Enum use.... having to manually test the value each time to confirm that the db value is one that i expect in my business logic later
b) Continue to use UserRoleEnum but lose the ability to declare multicolumn uniqueconstraints using the class attribute, and probably have to create these manually using a subsequent db migration script?
Is there any way to make the enums and the multicolumn constraint play nicely, out of the box?

This issue was because enum properties were using the default string definition fallback of VARCHAR(MAX) which SQL Server doesn't let you create indexes on whereas the column definition of a string property is VARCHAR(8000).
This issue is now resolved from this commit which now uses the VARCHAR(255) string definition of the EnumConverter Type Converter. This change is available from v4.5.5 that's now available on MyGet.
Otherwise you can also change the size of the column definition to match a string property by adding a [StringLength] attribute, e.g:
[CompositeIndex(true, nameof(UserId), nameof(UserRole))]
public class User
{
public long UserId { get; set; }
[StringLength(8000)]
public string UserRole { get; set; }
}

Related

How can I delete all records from a table?

I've been searching for an answer on how to delete ALL records from a table using LINQ method syntax but all answers do it based on an attribute.
I want to delete every single record from the databse.
The table looks like so:
public class Inventory
{
public int InventoryId { get; set; }
public string InventoryName { get; set; }
}
I'm not looking to delete records based on a specific name or id.
I want to delete ALL recods.
LINQ method syntax isn't a must, bt I do prefer it since it's easier to read.
To delete all data from DB table I recommend to use SQL:
Trancate Table <tableName>
Linq is not meant to change the source. There are no LINQ methods to delete or update any element from your input.
The only method to change you input, is to select the (identifiers of the )data that you want to delete in some collection, and then delete the items one by one in a foreach. It might be that your interface with the source collection already has a DeleteRange, in that case you don't have to do the foreach.
Alas you didn't mention what your table was: Is it a System.Data.DataTable? Or maybe an Entity Framework DbSet<...>? Any other commonly used class that represents a Table?
If you table class is a System.Data.DataTable, or implements ICollection, it should have a method Clear.
If your tabls is an entity framework DbSet<...>, then it depends on your Provider (the database management system that you use) whether you can use `Clear'. Usually you need to do the following:
using (var dbContext = new MyDbContext(...))
{
List<...> itemsToDelete = dbContext.MyTable.Where(...).ToList();
dbContext.MyTable.RemoveRange(itemsToDelete);
dbContext.SaveChanges();
}

Grails: domain properties are mandatory by default and Id is not generated

I am new to Grails. I installed Grails 2.4.4 version and Spring Tool Suite.
I created Grails project and domain ,controller classes. But i am getting all the fields as mandatory by default and "id" is not generated. Need some help.
Domain Class:
package org.example.pomorodo
class Task {
String summary
String details
Date dateCreated
Date deadLine
Long timeSpent=0L
static constraints = {
}
}
Controller Class:
package org.example.pomorodo
class TaskController {
static scaffold =Task
}
Do you mean you can't access the "id" property after saving your domain object with GORM? Or just that the generated code doesn't have an "id" property explicitly defined? If it's the latter, don't worry. The "id" property is automatically injected by metaprogramming black-magic by the framework. If it's the former, something else is wrong, as you should definitely have a valid "id" after saving a domain object.
On the mandatory fields: Use the constraints block to toggle fields to nullable = true. Example:
package org.example.pomorodo
class Task {
String summary
String details
Date dateCreated
Date deadLine
Long timeSpent=0L
static constraints = {
summary(nullable:true)
details(nullable:true)
}
}
You can also modify default constraints globally. See the constraints documentation for more details.
Recently I got a query regarding mapping a database table which do not have any id and version. For example the table have two varchar fields username and password nothing more than that.
Although it was something strange for me that table doesn’t have the id field. The good thing is that the username is a primary key in the table and this is not auto incremented user want to create it by his own method.
The good thing about grails is, in most of the cases you get your answer in the docs http://grails.org/doc/latest/ . So in this case we just need to change the id field in grails domain like this
class Test {
String username
String password
static mapping = {
id name: 'username'
version false
id generator: 'assigned'
}
static constraints = {
username(nullable: true)
}
}

Programmatically Change Database Table EntityFramework Model Object Refers to

Question is in the title. Can we programmatically change the database table which an object in the Model class, like one below, refers to and continue to operate on the new table?
public class Word
{
public int ID { get; set; }
public string Text { get; set; }
}
This originally refers to "Words" table automatically in EntityFramework, is there a way to change it before/during runtime? If so, how?
EDIT:
I get all the string used in Views in the project from the database table, "Words", by their ID's. Now, what I want is, a user enters a new language to system, and a new table will be created, for example WordsEnglish. From then, the Word object will refer to WordEnglish, if user selects English as language.
It would be desirable with a use case to better understand what you are trying to accomplish, but here goes...
In the DbContext.OnModelCreating method you can configure the model, e.g.
// Removes pluralization convention for all tables.
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
or
// Specific table name for Word Entity.
modelBuilder.Entity<Word>().ToTable("TableContainingWords");
If you are changing your model, Code First Migrations might be what you need.
I havent found a way to truly dynamically extend an EF model at runtime. Given what goes on in DB context inherited class, the use of generated views for performance and a model class approach, avoiding recompilation seems hard. I have generated code, compiled and access this using assembly discovery approaches. But this is all unsatisfactory from my viewpoint , so i have stopped investigating this path. Very clunky outcome.
Ironically the topic you provide as a use case for such a problem, is one that doesnt need dynamic EF in my view.
I have exactly the same use case, language specific look for messages/labels etc Ie a language specific textpool.
Why not add language to the class/table.
Use a table or Enum for supported languages.
Use Language in the Textpool table/s
Use a different model class for presentation. (view model).
So you can present it the way like .
public class Word
{
Guid ID {get;set;} // logical key is WordID + Language
public int WordID { get; set; } // implement with new id or 2 field key
public Language Language {get;set;} // see cultureInfo for more details
public bool IsMaster {get;set;}
public string Text { get; set; } // consider renaming due to reserved word implications
}
public class language
{
int ID,
String Lang
}
}

Can't Persist Field to Aspnet_Users via NHibernate/ActiveRecord

I'm using ActiveRecord with NHibernate on the backend. I've set up a mapping for Users; I can create/retrieve/register users without any issues.
I now want to add an association called Role to my users (many users per role). I've created the appropriate Role class, tables, data, etc. and everything seems to be working on that end as well.
The problem is that when I save a user and associate a Role, that association does not persist to the database.
I've added a RoleId (int16) column to the aspnet_Users table to match the Role table's Id (int16) column. I've tried using Save and SaveAndFlush without success.
Here's some code:
Role superUser = Role.First(r => r.name == "Super User");
User me = User.First(r => r.UserName == myUserName);
me.Role = superUser;
me.Save(); // Or: SaveAndFlush
When debugging, I can see the association on the objects when they're saved (i.e. me.Role is not null and has the right attributes/properties/etc.) However, when I look at the database, the RoleId value for that user is still NULL. (SaveAndFlush doesn't make a difference.)
What am I missing?
I've read somewhere on SO that extending the users table is usually done by adding another table and linking the two by a foreign key; I assume the classes would then use inheritance by composition for the new ExtendedUser class. Assuming I don't want to go that route, why isn't this working? Is it because of the specific ASP.NET MVC stored procedures et. all?
Some relevant mapping:
[ActiveRecord("aspnet_Users", Mutable = false)]
public class User : ActiveRecordLinqBase<User>
{
[PrimaryKey(PrimaryKeyType.Assigned)]
public Guid UserId { get; set; }
// ...
[BelongsTo("RoleId", Cascade = CascadeEnum.SaveUpdate)]
public Role Role { get; set; }
}
[ActiveRecord]
public class Role : ActiveRecordLinqBase<Role>
{
[PrimaryKey]
public int Id { get; set; }
// ...
[HasMany(Inverse = true)]
public IList<User> Users { get; set; }
[Property]
public string Name { get; set; }
}
Edit: mutable="false" - this clearly stands that entity is read only, which is the source of your problem.
Immutable classes, mutable="false", may not be updated or deleted by the application. This allows NHibernate to make some minor
performance optimizations.
Also:
I believe that you need to have cascading defined. You are not saving just the entity itself but also reference to other entity. Use attributes, fluent config or hbml to define this the way you need. Here are the cascading options:
Here is what each cascade option means:
none - do not do any cascades, let the users handles them by
themselves.
save-update - when the object is saved/updated, check the assoications and save/update any object that require it (including
save/update the assoications in many-to-many scenario).
delete - when the object is deleted, delete all the objects in the assoication.
delete-orphan - when the object is deleted, delete all the objects in the assoication. In addition to that, when an object is
removed from the assoication and not assoicated with another object
(orphaned), also delete it.
all - when an object is save/update/delete, check the assoications and save/update/delete all the objects found.
all-delete-orphan - when an object is save/update/delete, check the assoications and save/update/delete all the objects found. In additional to that, when an object is removed from the assoication and not assoicated with another object (orphaned), also delete it.
You may want to read this article.

Can't perform Create, Update or Delete operations on Table because it has no primary key

I've been trying to insert row in the table having an identity column RequestID (which is primary key as well)
HelpdeskLog logEntry = new HelpdeskLog { RequestBody = message.Body };
if (attachment != null)
logEntry.Attachments = Helper.StreamToByteArray(attachment.ContentStream);
Database.HelpdeskLogs.InsertOnSubmit(logEntry);
But my code inevitably throws following error
Can't perform Create, Update or Delete operations on Table because it has no primary key.
despite primary key column exists indeed
That's what I tried to do:
To look in debugger the value of identity column being inserted in object model. It is 0
To insert manually (with SQL) fake values into table - works fine, identity values generated as expected
To assure if SQLMetal has generated table map correctly . All OK, primary key attribute is generated properly
Nevertheless, neither of approaches helped. What's the trick, does anybody know?
I've also had this problem come up in my C# code, and realized I'd forgotten the IsPrimaryKey designation:
[Table (Name = "MySessionEntries" )]
public class SessionEntry
{
[Column(IsPrimaryKey=true)] // <---- like this
public Guid SessionId { get; set; }
[Column]
public Guid UserId { get; set; }
[Column]
public DateTime Created { get; set; }
[Column]
public DateTime LastAccess { get; set; }
}
this is needed even if your database table (MySessionEntries, in this case) already has a primary key defined, since Linq doesn't automagically find that fact out unless you've used the linq2sql tools to pull your database definitions into visual studio.
LINQ does not allow to insert data into table without primary key. To achieve the insert data with table without primary key you can either use store procedure or create a query and execute using LINQ. Below link provide good explanation of the same.
Can't perform Create, Update or Delete operations on Table(Employee) because it has no primary key
Delete the table and then reinsert it. You must make sure there is a little small key next to the field before you do this. Recompile your project and all should be fine.
Just because you updated the dabase does not mean the DBML file somehow automatically updated. It does not, sorry.
As the the table has the primary key in SQL Server, re-addthe table in the linq2sql designer.
If that were not the case, you can configure which properties are part of the primary key by hand on the designer.

Resources