Microsoft.Azure.Cosmos.Tables to Azure.Data.Tables migration: TableEntity Inheritance - c#

I am trying to migrate some legacy code from Microsoft.AzureCosmos.Tables to Azure.Storage.Tables. The TableEntity class is sealed in Azure.storage.Tables, so how do I fix this?
public class HistoricalValues : TableEntity
{
public string tName { get; set; }
public double tValue { get; set; }
public int fTagId { get; set; }
public string date { get; set; }
}
Do I just add the PartitionKey, RowKey, eTag, etc properties? Eg public string PartitionKey { get; set; }?
I don't really understand inheritance, so pointing me at a decent explanation/sample code would also be appreciated.

I've been migrating some legacy code myself. Azure.Storage.Tables follows a slightly different albeit improved paradigm for working with CosmosDB and Azure tables. Instead of inheriting TableEntity, your table entity classes implement ITableEntity, which as you mentioned requires you to add the RowKey, PartitionKey, ETag and Timestamp properties.
There are other changes besides the table entity implementation. This article has some good information with a walkthrough using ITableEntity.
The Microsoft information on this is a little less helpful, especially for migrating existing code from TableEntity to ITableEntity. Here's that documentation.

Related

Which entity design for hierarchy tree in asp.net mvc-application

I just can't decide on which approach to choose to be able to have a hierarchial tree with partially different object types. The application is Asp.Net MVC and I'm using entity framework code first. My hierarchial tree is an information content structure. Each node in the tree can be of either one of my three implemented types.
For now, Table-per-type (TPT) seems to be my best choice of design but what do you think? Any drawbacks with my choice of design? Should the base class have a discriminator field, for example?
To illustrate, below's an pseudo example of my current design.
Regards, Clas Ericson
public abstract class PageObject
{
public int ID { get; set; }
public int? ParentID { get; set; }
public string Title { get; set; }
public virtual PageObject Parent { get; set; }
public virtual ICollection<PageObject> Children { get; set; }
}
[Table("LinkPage")]
public class LinkPage : PageObject
{
public string Url { get; set; }
}
[Table("FramedPage")]
public class FramedPage : LinkPage
{
public int? MinHeight { get; set; }
public int? MinWidth { get; set; }
}
[Table("ContentPage")]
public class ContentPage : PageObject
{
[DataType(DataType.Html)]
[AllowHtml]
public string Content { get; set; }
}
public class InheritanceMappingContext : DbContext
{
public DbSet<PageObject> PageObjects { get; set; }
}
Should the base class have a discriminator field, for example?
You don't have to declare it explicitly while using any of these approaches. Discriminator field will be automatically added as a table field by Entity Framework when using TPH approach, because it stores everything in 1 table, and this field acts like an pointer to which class this record belongs.
For now, Table-per-type (TPT) seems to be my best choice of design but
what do you think?
You should realize, that this is completely opinion-based question, moreover it depends on your needs. Each approach has it's advantages and vice versa.
TPH will grant you best performance, because all the data is selected by 1 query without any JOINS, but it requires properties in subclasses to be Nullable in the Database. Also TPH violates the third normal form (price for performance)
The primary advantage of TPT strategy is that the SQL schema is normalized but performance can be unacceptable for complex class hierarchies because queries always require a join across many tables
http://www.entityframeworktutorial.net/code-first/inheritance-strategy-in-code-first.aspx

multiple tables from the same model

I am attempting to use several tables that all follow the same model, this is so that eventually if my application scales farther than needing a single database, the framework has already been laid.
Multiple object sets per type are not supported. The object sets 'Entity' and 'Reddit' can both contain instances of type 'Project.Models.Entity'.
I know this error comes from this section of my dbcontect model:
public DbSet<Entity> Entity {get; set;} //local users
public DbSet<Entity> Reddit { get; set; } //users who registered through reddit
public DbSet<Entity> Twitter { get; set; } //user who registered through twitter
I cant seem to find a way to make this work. I know existing topics cover why this is a problem, but the only solution I seem to find is "well make another database" which while seems simple, still doesn't really explain the issue or how to actually fix it through code.
(using entity framework 6)
This was extracted from the question.
I found the solution and It's so simple I'm rather ashamed that I even had to ask.
just make a new DBcontext for each table
which looks like
RedditDB.cs
public RedditDB() : base("name=Database")
{
}
public DbSet<Entity> Reddit { get; set; }
TwitterDB.cs
public RedditDB() : base("name=Database")
{
}
public DbSet<Entity> Twitter{ get; set; }
and in the controller just put
RedditDB _RDB = new RedditDB();
TwitterDB _TDB = new TwitterDB();
Use inheritance to create a new class with the same properties as the existing Entity.
public class Twitter
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<EntityC> Lines { get; set; }
}
public class Reddit : Twitter
{
// leave this empty
}
This is better than using separate DB contexts because it is easier to query a single context; you can join tables etc.

Creating a master table with two child tables linking one-to-zero-or-one with EF 4.1

Using MVC EF4.1, I am trying to link a table (TableMaster) to TableChildOne (relationship one-to-zero-or-one) and also to TableChildTwo (also one-to-zero-or-one).
TableChildOne and TableChildTwo are not directly linked.
TablechildOne and TableChildTwo needs to share the primary key of TableMaster (I read this is not possible, any workarounds?)
I am including an image to make this a bit more clear, not sure if there should be foreign keys added somewhere, this is not an actual model created by the code, but is what i would like. not sure if there should be foreign keys somewhere?
image : http://www.davidsmit.za.net/img/untitled.png
My code below compiles, but when trying to add a controller, I get the error :
"An item with the same key has already been added"
public class TableMaster
{
public int TableMasterID { get; set; }
public DateTime ReportDate { get; set; }
public virtual TableChildOne TableChildOne { get; set; }
public virtual TableChildTwo TableChildTwo { get; set; }
}
public class TableChildOne
{
[Key]
public int TableMasterID { get; set; }
public String Description_1 { get; set; }
public virtual TableMaster TableMaster { get; set; }
}
public class TableChildTwo
{
[Key]
public int TableMasterID { get; set; }
public String Description_2 { get; set; }
public virtual TableMaster TableMaster { get; set; }
}
public class Context : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TableMaster>()
.HasOptional(p => p.TableChildOne).WithRequired(p => p.TableMaster);
modelBuilder.Entity<TableMaster>()
.HasOptional(p => p.TableChildTwo).WithRequired(p => p.TableMaster);
}
When I remove the second table completely, it works fine.
I used the below link as an example (tables OfficeAssignment and Student), which shows how to link a table one-to-zero-or-one. But I have trouble adding another table with the same linkage:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
Any help will be appreciated.
Thanks
appelmeester
Could you give more background about why you want to do this? If you are sharing the primary key across three tables you are partitioning data. What development scenario are you trying to address. It sounds like you might be wanting to map an object inheritance, is that right?
If you truly only have a couple of Descriptions, then this is really just one table.
EDIT:
Cool. Because the business context of this request is a bit vague, I can't quite understand still, sorry. If you have a TableMaster and then some child tables, then this sounds like an inheritance tree. So with EF, you can choose many different strategies to model this (TPH, TPT etc). For this, I would suggest looking into TPT because this might allow you to get the granularity for how you want to clean up the data. Also, you get the benefit that the tables will be created, by default, largely like you have specified. Check this out for reference.

EF 4.2 Code First, how to map with fluent API?

(Since i have a database predefined i can't let EF recreate it).
This the mapping i use now (works but i want to rewrite using fluent api):
public class League
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid LeagueId { get; set; }
....
#region References
public virtual ICollection<News> News { get; set; }
#endregion
}
public class News
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid NewsId { get; set; }
public Guid LeagueId { get; set; }
....
#region References
[ForeignKey("LeagueId")]
public virtual League League { get; set; }
#endregion
}
Now, how can i map this using the fluent API?
Update
Wrote this and it works, but is there a simpler version?
modelBuilder.Entity<League>().HasMany(x => x.News).WithRequired(y => y.League).HasForeignKey(c => c.LeagueId);
Update 2
I added those missing from the classes. But the problem is that if i leave it at that and try it, it fails. I need to specify a key somewhere.I can't let EF create the database and it refuses to just operate with tables.
You should look at this article for example: http://www.codeproject.com/Articles/184133/Using-Entity-Framework-4-1-Code-First-with-an-exis
The base part, is that you should remove default db initializer:
Database.SetInitializer<YourContext>(null);
And this should prevent EF from trying to change your db or throw errors. It will just try to work with what you give it.

Entity Framework 4: Many to Many relationship IQueryable instead of ICollection

Good morning everyone,
I am trying to tackle a problem I run into with EF code first. My schema is the following
public class Article : IUrlNode
{
[Key]
public Guid ArticleID { get; set; }
public string Title { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public string Summary { get; set; }
[System.ComponentModel.DataAnnotations.InverseProperty("CategoryArticles")]
public virtual IQueryable<Category> ArticleCategories { get; set; }
public string FriendlyUrl
{
get;
set;
}
}
[RouteChild("CategoryArticles")]
public class Category : ContentNode
{
public Guid ServiceId { get; set; }
[System.ComponentModel.DataAnnotations.InverseProperty("ArticleCategories")]
public virtual IQueryable<Article> CategoryArticles { get; set; }
}
I have written code with which I am able to retrieve a category from the database without actually knowing that its a category. From then on I must retrieve a single article of that category again without knowing that its an article. For categories I am relying on the ContentNode base class and for Articles on the IUrlNode interface.
Category retrieval works fine and with a single query but after I actually get the category I have to use reflection to get the navigation property pointed by the RouteChild attribute to find that single article that matches my criteria. Problem is that the navigation property type is ICollection which means that it will at best use lazy loading and will bring all the articles from the database and will find the one I am looking for in memory.
My problem is also described in this previous post (not by me):
Entity Framework Code First IQueryable
Is there a way to have that navigation property as IQueryable or some other design that can go around this limitation?
No there is no way to have navigation property as IQueryable but you can change the collection to IQueryable by using:
IQueryable<Article> query = context.Entry(category).Collection(c => c.articles).Query();
query.Where(...).Load();
Generally your "algorithm" looks pretty strange. You want to work with base class but in the same time you want to access child properties. That sounds wrong and it can most probably be solved in better way (non "generic" way is also better).

Categories

Resources