I'm fairly new to asp mvc and I'm currently trying to limit the text on an item in my site, how can i limit the text for:
#Html.DisplayFor(model => model.Text)
I have tried just creating another item in the model like this:
public string Text {get; set; }
private string _limitText;
[StringLength(30)]
public string limitText
{
get
{
return (_limitText = this.Text)
}
set
{
_limitedText = Text;
}
}
However i get errors when updating database with the Nuget Console:
"String or binary data would be truncated. the statement has been terminated"
All help appreciated.
It seems you are using EF code first and trying to upgrade your DB using code first migrations.
Since you have already created table with VARCHAR(MAX) length (If you do not specify length on your property it will be considered as max length by EF), you will need to first delete all records from DB which has length more then 30 for limittext column. Else you wont be able to upgrade your version using code first migration.
If you do not want to loose your data then clone your table and then migrate your database and then copy your data back to original table.
You can clone table using following query
SELECT *
INTO CustomerClone
FROM Customer
Your chief problem here is that your new property, limitText has both a getter and setter and you're filling it with the full text from Text. If a property has a getter and setter, then Entity Framework persists it to the database. That alone is probably not ideal, since you're basically duplicating data, but let's say you wanted it to actually be persisted. It's value is set to the full string of Text, but it's going to then be persisted into a column that has a maxlength of 30 characters, hence the error. There's many ways to fix this problem. First, you can simply set the value to just the truncated string:
_limitText = this.Text.Substring(0, 30);
Then, it will save fine because the value will always be 30 characters of less. However, more likely than not, you simply shouldn't persist this field. That can be accomplished by either 1) removing the setter or 2) decorating the property with [NotMapped].
Also, you could simply not use this extra property at all. There's no need to use Html.DisplayFor here, so you could simply just do the following in your view instead:
#Model.Text.Substring(0, 30)
There are simple 2 ways how the issue can be solved:
First, you can use attribute maxlength to specify maximum length of the text that can be input. In this case you need to change DisplayFor to TextBoxFor and use maxlength attribute:
#Html.TextBoxFor(model => model.Text, new { maxlength=30 } )
Second, you can take first 30 symbols of the property by using Substring function. This is not very nice approach but it works.
Related
How can we safely change the datatype of a property of a Starcounter database class if the corresponding table has existing data?
Example
existing: int PostalCode
desired: string PostalCode
Changing property of a database class means refactoring database schema, i.e., changing type of the corresponding column. Such changes are not supported seamlessly and no build-in tool is provided by Starcounter. It can be done manually, but it is quite cumbersome.
I see two approaches:
Unload the database using stardump tool and modifying the schema and data using external tool such as SQLite.
Through several steps of changing the app schema first move data from int column into string column and then rename column into the original one.
Remember to always backup your database.
I describe the second approach in more details.
Step I: move data from int to string
Add new property of string type to the database class, e.g., PostalCodeString
Add and execute application code, which will go through all instances of the class and set PostalCodeString to the value converted from original int PostalCode
Stop the application and execute SQL statement to drop the column: ALTER TABLE TheClassName DROP COLUMN PostalCode
Remove the old property PostalCode from the class definition and remove the conversion code.
Start the application and test that it works as expected
Step II: rename column
Add new property with the old column name, i.e., PostalCode of type string
Move data from PostalCodeString to PostalCode in the similar way as step I, i.e., by application code going through all instances of the class.
Drop column PostalCodeString
I haven't tested these steps myself, but I expect it to work. The main concern is creating PostalCode in step II.
EDIT: the drop column SQL statement is only fully supported in latest release candidates since December 18, 2017.
If PostalCode is just a int then this should work.
PostalCode.ToString();
I am using the answer of this question How to automatically generate unique id in sql server to create a custom id for a table.It worked perfectly.Now I have a column which holds the values such as UID00000001 UID00000002 and so on. Suppose the last value in this column is UID00000003.Now I want to calculate the value for the row which hasn't been inserted yet via C# in one of my .aspx pages.In this case UID00000004. How can I achieve this value?
Any help would be appreciated.
Thank you.
If you are not required to generate these identifier at database level (e.g. some other processes insert records there), you can pre-generate them within your application. Something like above:
class Generator
{
public static int UniqueId = 0;
public static int GetNextId()
{
return Interlocked.Increment(ref UniqueId);
}
}
Then, your code can preallocate these identifiers and also format those strings. If multiple users access the same functionality, they will receive other identifiers. However, if one does not (successfully) performs a save operation, those identifiers will be lost.
You need to execute this query to get the next identity which will be generated for the table:
SELECT IDENT_CURRENT('table_name')+1;
For your case, it will have some other info concatenated with the next identity so the query will be like this:
SELECT 'UID' + RIGHT('00000000' + CAST(IDENT_CURRENT('table_name')+1 AS VARCHAR(8)), 8)
Of course you will need to write the C# code to send that query to the SQL Server.
Having said that, keep this in mind: When you get the value from that call and hold onto it, if during the time you are holding the value a record is inserted into that table, then the value is no longer the next value.
If you need the identiy value after a record is inserted in your application, please refer this answer.
I'm fighting trough with Entity Framework 6 and MySQl Database
I got everything to work, however I'm confused with dates or not obligatory values.
In my database, in "Users" table I have column "RegistrationDate" which has default value of "CURRENT_TIMESTAMP"
what is mean that if value not provided at insertion time it will insert default value = date time of the server
I got my schema reverse engineered into C# and all perfectly works, however when I insert "User" without setting a date to "RegistrationDate" property, it insert into Database new date as "0001-01-01 00:00:00" and ignore "CURRENT_TIMESTAMP".
So im wondering how to set it to ignore "RegistrationDate" and do not insert anything into db if it wasn't specifically set to some date?
I have a guess that the SQL EF generates is setting the field value. Even if you don't set in code, EF doesn't know that the database has a default value, and doesn't know that he should ignore it.
This article, from 2011, says that there is a DatabaseGenerated attribute, which you could use like this:
[DatabaseGenerated(DatabaseGenerationOption.Computed)]
public DateTime RegistrationDate { get; set; }
So, EF now knows that it should retrieve the data when you query the database, but should rely on the database to set the value.
However, I don't know what it would do if you explicitly set the value. Maybe it will ignore it, which may be not what you really want.
I didn't test it, it's just a guess, but it's a nice solution in my opinion.
[Edit1] Some months ago, I saw this video, and the guy does something like this in his DbContext class (i believe you have it) at 49:12 (the video is in portuguese)(i have modified the code, but didn't test it):
//This method will be called for every change you do - performance may be a concern
public override int SaveChanges()
{
//Every entity that has a particular property
foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("YourDateField") != null))
{
if (entry.State == EntityState.Added)
{
var date = entry.Property("YourDateField");
//I guess that if it's 0001-01-01 00:00:00, you want it to be DateTime.Now, right?
//Of course you may want to verify if the value really is a DateTime - but for the sake of brevity, I wont.
if (date.CurrentValue == default(DateTime))
{
date.CurrentValue = DateTime.Now;
}
else //else what?
{
//Well, you don't really want to change this. It's the value you have set. But i'll leave it so you can see that the possibilities are infinite!
}
}
if (entry.State == EntryState.Modified)
{
//If it's modified, maybe you want to do the same thing.
//It's up to you, I would verify if the field has been set (with the default value cheking)
//and if it hasn't been set, I would add this:
date.IsModified = false;
//So EF would ignore it on the update SQL statement.
}
}
}
I think many of us have been caught out by default database values when dealing with EF - it doesn't take them into account (there are many questions on this - e.g. Entity Framework - default values doesn't set in sql server table )
I'd say if you haven't explicitly set a datetime and want it to be null, you'll need to do it in code.
I’m currently working on a project where we need to archive and trace all the modified data’s.
When a modification surrender, we have to kept theses information
Who has modified the data?
When?
And … that’s why I’m asking this question: Keep the previous
and the new value of the data.
Quickly, I have to trace every modification for every data.
Example :
I have a name field why the value “Morgan”.
When I modify this value, I have to be able to say to the user that the 6th of January, by XXX, the value changed from “Morgan” to “Robert” …
I have to find a clean and generic method to do this because a large amount of data is concerned by this behavior.
My program is in C# (.NET 4) and we are using Sql Server 2008 R2 and NHibernate for the object mapping.
Do you any ideas, experience or solution about how to do a thing like that?
I am a little confused about at what point you want to have the old vs new data available. But, this can be done within a database trigger as in the following question:
trigger-insert-old-values-values-that-was-updated
NHibernate Envers its what you want :)
You must use NHibernate 3.2+ (3.2 is the current release).
Its easy like
enversConf.Audit<Person>();
You can get info here and here
I've been in the same situation as you. I ended up doing in this way:
Save an ActivityEntry in the database containing an identity column (if you have multiple objects that change), an action-indicator (could be "User changed firstname", as a int), date field, userId and most important a parameter field.
Combining the values from the parameter field and the action-indicator I'm able to make strings like "{0} changed {1}'s firstname from {2} to {3}" where my parameter values could be "John;Joe".
I know it feels kinda wrong saving these totally loosely typed values in the database, but I believe it's the only way around, without having a copy of each table.
I posted this question yesterday evening, which has led me to discover a huge problem!
I have a decimal column in my database called Units, anytime I set the value of the column to a NON ZERO, and SubmitChanges the column updates with the new value. If I try to set the value of the column to ZERO, the SubmitChanges does not update the column.
data.Units = this.ReadProperty<decimal>(UnitsProperty);
data.UnitPrice = this.ReadProperty<decimal>(UnitPriceProperty);
data.Price = this.ReadProperty<decimal>(PriceProperty);
I've taken a look at the DataContext log and I can see that the field with the ZERO value is not included in the query. Even if I try to hard code the change Linq ignores it.
data.Units = 0;
data.UnitPrice = 0;
data.Price = 0;
Needless to say this is killing me! Any ideas why this happening?
Solution
I figured out my problem with the help of the SO community. My problem was being caused by the fact when I created my entity to attach, the default value of the column was set to zero, so when it tried to assign the value to zero ... LinqToSql says hey ... nothing changed, so I am not updating the value.
What I am doing now ... just to make it work is the following:
ctx.DataContext.InvoiceItems.Attach(data, true);
That seems to force all the values to write themselves to the database. This works for now.
I have tried to reproduce this with a the following code, but for me it works.
using (DataClasses1DataContext ctx = new DataClasses1DataContext())
{
var obj = ctx.DecimalColumnTables.First();
Debug.Assert(obj.B != 0);
obj.B = 0;
ctx.SubmitChanges();
}
So I think there must be something special in your domain that causes this. I suggest you to create a such simple repro with your domain model and see what happens.
LINQ to SQL ignores updates to the current value, so if the field was already zero, you may not see any updates.
Off: The OR/M you use is LINQ to SQL. LINQ is the name of the querying capability in .NET, but LINQ does not define nor implement any update logic. So the issue relates to LINQ to SQL, not LINQ.
Obvious question, but are you sure the column is mapped in the dbml / mapping file?
Also - is it a calculated column? (i.e. price => units * unitprice)
I figured out my problem with the help of the SO community. My problem was being caused by the fact when I created my entity to attach, the default value of the column was set to zero, so when it tried to assign the value to zero ... LinqToSql says hey ... nothing changed, so I am not updating the value.
What I am doing now ... just to make it work is the following:
ctx.DataContext.InvoiceItems.Attach(data, true);
That seems to force all the values to write themselves to the database. This works for now.
Some more information ... I figured out my problem ... it's more of a lack of understanding about LinqToSql ... where I am doing:
private void Child_Update(Invoice parent)
{
using (var ctx = Csla.Data.ContextManager
.GetManager(Database.ApplicationConnection, false))
{
var data = new Gimli.Data.InvoiceItem()
{
InvoiceItemId = ReadProperty(InvoiceItemIdProperty)
};
ctx.DataContext.InvoiceItems.Attach(data);
if (this.IsSelfDirty)
{
// Update properties
}
}
}
I thought this would load the original values ... what happens is that it creates a new object with default values ... empty values, like 0 for decimals, Guid.Empty for uniqueidentifiers and so on.
So when it updates the properties it sees the Units already as 0 and it sets it to zero. Well LinqToSql doesn't recognize this as a change so it doesn't up date the field. So what I have had to do is the following:
ctx.DataContext.InvoiceItems.Attach(data, true);
Now all the modifications are generated in the update statement whether there is really a change or not. This works ... seems a bit hackish!
The correct answer is as many pointed out to use the special overload of Attach which accepts a boolean parameter to consider it as modified, (make the mistake of using another overload and it simply won't work):
ctx.DataContext.InvoiceItems.Attach(data, true);
Note however that you still might need to have a "Version" column in the table of type "timestamp".
I had this problem and all the suggestions I'd seen didn't apply or work.
But I found I had made a very simple mistake!
When updating the property I was actually calling a custom Set method (because there were other things that needed to be changed in response to the main property in question).
After hours of head scratching I noticed that my Set method was updating the private member not the public property, i.e. this._Walking = value;
All I had to do was change this to this.Walking = value; and it all started to work!