Rename Navigation Property in Entity Framework 5 does not update code - asp.net

I would like to rename a navigation property and access that object in code by the new name I gave. I have renamed one of my user properties to a more meaningful name rather than 1,2,3...etc.
In this example, I have renamed OGSMUser5 to OGSMUserResponsible in the model diagram.
I then tried to access this in code, but it can't find my renamed property OGSMUserResponsible.
#contImprovement.OGSMUserResponsible.FullName
When I look at the code in the model generated from Entity Data Model, I see that the code did not change for the newly renamed model, which explains why I can't access it.
public virtual OGSMUser OGSMUser { get; set; }
public virtual OGSMUser OGSMUser1 { get; set; }
public virtual OGSMUser OGSMUser2 { get; set; }
public virtual OGSMUser OGSMUser3 { get; set; }
public virtual OGSMUser OGSMUser4 { get; set; }
public virtual OGSMUser OGSMUser5 { get; set; }
I have seen somewhat similar questions to this, but the answers I have seen I can't believe is the only option. They have been manually creating a new property with the name you want (what I renamed mine to in the navigation property) in a partial class and return the navigation property with the number in the name to help clean it up. I can't believe that this is the best way to accomplish what I am looking for.
Thanks for the help.

You probably didn't run the T4 template transformations.
Just right click your .tt files (they are under your .edmx file in the Solution Explorer tree) and run them. Alternatively, you can run all tt by clicking the button in Visual Studio's toolbar.

Related

How can I store multiple images in a database with a Blazor application?

I have an application that shows a form to the users. The form is taken by the server and stored in a database where the information can be read on another page in the application. Part of the form takes an image, where the image is converted to a Base64 string and sent to Azure to be stored, and the URL to the image is stored in the database as a string. This all works fine. My trouble comes from trying to implement a feature where users can select multiple images.
I tried changing the string Image {get;set;} to a List<string> {get;set;} where the database would just store a list of the URLs where I could iterate through them in the application. This obviously did not work, as through some research, I learned that databases cannot store lists.
I am now wondering what I can do here. Is there a simpler way of doing this that I'm missing? What am I doing wrong?
I tried changing the string Image {get;set;} to a List
{get;set;} where the database would just store a list of the URLs
where I could iterate through them in the application. This obviously
did not work, as through some research, I learned that databases
cannot store lists.
You can try to use the following methods:
Add separator between the Image urls. Use string Image {get;set;} to store the image urls, the value like this: "image1url,image2url,etc" (use the , as the separator). You can consider using the String.Join Method.
Create a new Image table to store the Image information (contains ID, Name, Urls), then configure one-to-many relationship between the Main table and the Image model. In the Main model, use navigation property to add the Image. Code like this:
public class Main
{
public int Id { get; set; }
public string Name { get; set; }
public List<Image> Images { get; set; }
}
public class Image
{
public int Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
}
More detail information about the Entity relationship, see:
Relationships
Configuring One To Many Relationships in Entity Framework Core
Saving Related Data

Xamarin Forms Add List to SQL database

I have a problem. I created the following class:
public class KnownDevice
{
public int Id { get; set; }
public string Name { get; set; }
public string IP { get; set; }
public string MAC { get; set; }
public string Type { get; set; }
public List<TriangleRegistryObject> triangles { get; set; }
public List<HexagonRegistryObject> hexagons { get; set; }
}
Now, I want to create a Database on the mobile phone itself, so I use the following code to create the table:
database = DependencyService.Get<ISQLite>().GetConnection();
database.CreateTable<KnownDevice>();
But the code crashes on the second line with the error:
System.NotSupportedException: 'Don't know about
System.Collections.Generic.List`1
Now on the internet I found that it is not allowed to add a List to a database, but I need the data in that list, so I have no idea how I can fix this problem. The list can contain arround 25 rows!
Any idea how I can solve this problem?
List<TriangleRegistryObject> is not a valid type for a SQLite database value. Your type of List<TriangleRegistryObject> does not match any of the clrType == typeof(XXXX) statements, so you get that exception. You will need to rethink the class structure a little to be able to use SQLite-net like that.
For more details about the SQLite database, you could download the source file from the link for reference.
https://learn.microsoft.com/zh-cn/samples/xamarin/xamarin-forms-samples/todo/
If you want to use ou could use List, you could use SQLite-Net Extensions instead of SQLite.
You could refer to the link. The SQLite-Net Extensions library direct to specific relationships in database.
How can you store lists of objects in SQLite.net?

Cannot drop database. Because it is in currently use. EF Code first approach

I am using code first entity framework approach. I have changed the name Plane_EcoClass to Plane_Class property to the table in the database. It is showing with old property name in the db .How can I update the new property name?. Please let me know how to resolve this error.
public class Plane
{
[Key]
public int Plane_id { get; set; }
public string Plane_Name { get; set; }
public string Plane_No { get; set; }
public string Plane_Class { get; set; }
public virtual List<User>Users { get; set; }
}
you need to add a migration and update the database for the change to affect the database. In the package manager console, type something like:
add-migration YourMigrationName
to create the migration. Review the migration code. Be aware that Entity Framework may try to drop the previously named column and add a column for the new name. This can potentially cause data loss. If this is the case and not desired, then you can manually change the code to use the RenameColumn method.
After adding the migration, you can apply it to the database by going back to the package manager console and typing:
update-database
and then hitting enter. At this point, the package manager console will give you some output regarding running migrations and your seed method and then the database should reflect the updated column name

Isolated RazorEngine failing to pass model to different AppDomain

When I render my template without the EditHistory member, this works. However, when I add that additional member that is within my application I get an exception Could not load file or assembly 'Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. Models is the project containing ContentModel, EditHistory and UserDetail.
public class ContentModel
{
public string Html { get; set; }
public string Title { get; set; }
public EditHistory History { get; set; }
}
public class EditHistory
{
public IReadOnlyCollection<UserDetail> Authors { get; set; }
}
public class UserDetail
{
public string Name { get; set; }
public string EmailAddress { get; set; }
}
I am wrapping ContentModel in a RazorDynamicObject as such:
Razor.Run("default.cshtml", typeof(ContentModel), RazorDynamicObject.Create(cm));
As mentioned above, it works without EditHistory being present, but fails when it is.
The sandbox is set up verbatim as per how it's done at https://antaris.github.io/RazorEngine/Isolation.html
How do I get it to work with complex custom types?
Running under ASP.NET.
Edit
I have created a minimal reproduction of the issue I'm facing. It's at https://github.com/knightmeister/RazorEngineIssue. If package restore fails, manually install-package razorengine.
First of all; I was never able to get your GitHub-code running. The following is based on my own reproducing code.
I think that you're getting Could not load file or assembly-exceptions because when you setup the sandbox AppDomain you're setting:
adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
This won't work in ASP.NET because assemblies are in the bin subfolder. To fix that, simply do this instead:
adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase
+ "\\bin";
However, ASP.NET will by default shadow copy assemblies. Therefore just doing this change will probably cause another exception:
ArgumentException: Object type cannot be converted to target type.
That's because there's a mixup between assemblies loaded in the default app domain and the sandbox. The ones in the default app domain are located in a temporary shadow copy location and the ones in the sandbox are located in the bin-folder of your web application root.
The easiest way to fix this is to disable shadow copying by adding the following line under <system.web> in your Web.config:
<hostingEnvironment shadowCopyBinAssemblies="false"/>
In addition; I think it's better and easier to skip using RazorDynamicObject and instead mark your models with [Serializable]. In fact I never got RazorDynamicObject working properly.
The rest of this answer summarizes what I did to come to this conclusion
I think that this is due to a bug or limitation in RazorEngine. (I'm not so sure about this anymore, it might very well be that shadow copying and RazorDynamicObject cannot work together)
I've spent a couple of hours trying to figure out how to get this working but I've always ended up with a security exception being thrown from RazorEngine.
There is, however, a possible workaround: Ditch RazorDynamicObject and mark your model classes as serializable.
[Serializable]
public class ContentModel
{
public string Html { get; set; }
public string Title { get; set; }
public EditHistory History { get; set; }
}
[Serializable]
public class EditHistory
{
public IReadOnlyCollection<UserDetail> Authors { get; set; }
}
[Serializable]
public class UserDetail
{
public string Name { get; set; }
public string EmailAddress { get; set; }
}
And do:
Razor.Run("default.cshtml", typeof(ContentModel), cm); // no RazorDynamicObject
I couldn't get your repro code running, so I created my own based on your code:
Create a new Console application (Visual Studio)
In the package manager console, run: install-package razorengine
Copy code from your repro:
Line 25-38 and 43-65 from:
https://github.com/knightmeister/RazorEngineIssue/blob/master/Global.asax.cs
All models from: https://github.com/knightmeister/RazorEngineIssue/blob/master/Models/Models.cs
Mark models with [Serializable].
Remove RazorDynamicObject
To ensure that we really can render user details from the authors list, change the test template to:
string template = "#Model.History.Authors[0].EmailAddress";
Also, to make that template work, change Authors in EditHistory from IReadOnlyCollection<> to IReadOnlyList<>
I created a GIST with the resulting code:
https://gist.github.com/mwikstrom/983c8f61eb10ff1e915a
This works for me. It prints hello#world.com just as it should.
ASP.NET will shadow copy assemblies by default and that will cause additional problems with sandboxing.
To get this working under ASP.NET you'll have to do the following changes:
Disable ASP.NET shadow copying by adding the following under <system.web> in your Web.config file:
<hostingEnvironment shadowCopyBinAssemblies="false"/>
Append \bin to the sandbox's application base path. So in createRazorSandbox(...) do:
adSetup.ApplicationBase =
AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "\\bin";
I have tested this and it works just fine. My test project is simply:
An empty ASP.NET Web Application (created with Visual Studio), with install-package razorengine
<hostingEnvironment shadowCopyBinAssemblies="false"/> in Web.config.
The following Global.asax.cs:
https://gist.github.com/mwikstrom/ea2b90fd0d306ba3498c
There are other alternatives (besides disabling shadow copying) listed here:
https://github.com/Antaris/RazorEngine/issues/224
I mostly don't use complex types but a general rule is usually that only primitive datatypes are transferred ok (my own rule, since values often get lost for me otherwise). However, when looking at some old source code I noticed I did use many complex types, but I populated them in the Controller (e.g. in Public ActionResult Index()). After some reading I think it might work if you use something similar to this (untested, MSDN source, 2nd source):
[MetadataType(typeof(EditHistory))]
public partial class ContentModel
{
public string Html { get; set; }
public string Title { get; set; }
public EditHistory History { get; set; }
}
[MetadataType(typeof(UserDetail))]
public partial class EditHistory
{
public IReadOnlyCollection<UserDetail> Authors { get; set; }
}
public class UserDetail
{
public string Name { get; set; }
public string EmailAddress { get; set; }
}

Entity Framework 4.1 Code First: Advice on persisting data from external source?

Part of my project is to persist data from another source. In this case we have an SAP data source that we will need to pull data from. I need to take the data from SAP and map it to entities I have in my application. Here is an example of an entity I have in my application:
public class Project : BaseEntity
{
public string Name { get; set; }
public string ProjectNumber { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string Currency { get; set; }
#region Navigation Properties
public virtual Address Address { get; set; }
public virtual CompanyCode CompanyCode { get; set; }
public virtual ICollection<Contact> TeamMembers { get; set; }
#endregion
}
As you can see, I have child objects that I map from SAP as well. I need some advice on the best way to insert and update my entities. I am struggling with knowing when to add (insert) entities to my context and when to attach (update) them, because SAP doesn't have knowledge of what my application may or may not have. I need to guard against duplicates, too. For example, should I perform a lookup of each child entity in my parent entity to see if they exist before I apply them to the parent? Then, add / attach the entire parent object to the context or handle each entity separately while still maintaing their relationships?
Yes you must manually test everything to make correct decision what must be inserted, updated or deleted. Depending on the application you can use some more complex queries to reduce number of round trips to the database - for example you can use single query with Contains to load all TeamMembers needed for processed Project or you can load Project with including all related data if you also need to test if project exists.
I did large synchronization application before and I end up with pre-loading all entities at the beginning with few queries and working completely in memory.
Don't forget to use DbSet's Local property or Find method to take advantage of already loaded entities.
You can also use some custom stored procedures to improve performance of this operation.

Resources