I have a pattern in my database tables for soft deleting. I want to generate Linq queries to fetch data that is not expired.
For example with the two tables below, a User can have multiple addresses. An address can be soft deleted by setting the SoftDeleteDate to Datetime.Now. When fetching the User we can create a query to exclude UserAddress where UserAddress.SoftDeleteDate is not null.
TABLE [dbo].[User](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[FirstName] [nvarchar](25) NOT NULL,
[SoftDeleteDate] [datetimeoffset](7) NULL
)
TABLE [dbo].[UserAddress](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[UserId] [bigint] NOT NULL,
[StreetName] [bigint] NOT NULL,
[City] [nvarchar](50) NULL,
[State] [nvarchar](50) NULL,
[SoftDeleteDate] [datetimeoffset](7) NULL
)
This is a simple use case. In practice an entity such as a user can be linked to child entities to several degrees of nesting.
Generic methods for fetching can be easily created using DbContext. These methods fetch nested entities using "Include". But linq has no concept of "Exclude"
T GetDataById<T>(long id)
{
return Context.Set<T>().Find(id);
}
I want to create a generic method that produces Linq queries that excludes any expired child entities to no more than three degrees of nesting. This way, when I fetch a User I can exclude expired UserAddresses.
I have seen some posts about PredicateBuilder http://www.albahari.com/nutshell/predicatebuilder.aspx but not sure if it can be used to generate a query with the needed filter.
Wondering if anyone out there has worked on this problem.
Related
I have a requirement to create a calculated column in a database table using EF6 code first. Below is the table definition I am trying to generate:
CREATE TABLE [Dim].[Account](
[pkAccount] [int] IDENTITY(1,1) NOT NULL,
[Account] [nvarchar](20) NULL,
[AccountDescription] [nvarchar](100) NULL,
[AccountGroup] [nvarchar](20) NULL,
[Chksum] AS checksum([Account],[AccountDescription],[AccountGroup])
) ON [PRIMARY]
I want the Chksum column to calculate a value when a select is executed and not calculated externally and stored as a static value.
I have tried modifying the DbMigration as below using the DefaultValueSql property:
AlterColumn("Dim.Account", "Chksum", b => b.Int(false, false, defaultValueSql: "checksum([Account],[AccountDescription],[AccountGroup])"));
This returned the error The name "[Account]" is not permited in this context.
Is there a way to achieve this?
My dapper code is given below with a select query:
const string Sql = #"SELECT [id]
,[groupName]
,[reqCap]
,[impCap]
,[player]
,[resumeDate]
,[whitelist]
,[blacklist]
,[Macros]
FROM [VideoServer].[dbo].[TagGroup]";
return await dc.Connection.QueryAsync<TagGroup>(Sql);
My table design is given below:
[id] [int] IDENTITY(1,1) NOT NULL,
[groupName] [varchar](500) NOT NULL,
[reqCap] [int] NULL CONSTRAINT [DF_TagGroup_reqCap] DEFAULT ((0)),
[impCap] [int] NULL CONSTRAINT [DF_TagGroup_impCap] DEFAULT ((0)),
[player] [varchar](500) NULL,
[resumeDate] [date] NULL,
[whitelist] [nvarchar](max) NULL,
[blacklist] [nvarchar](max) NULL,
[Macros] [nvarchar](max) NULL
When I run this select query in SQL Server Management Studio it is returning within 0 milliseconds. But the same query from dapper (above code) is taking too long.
Any ideas? Is this because of nvarchar(max)?
If I clear data in nvarchar(max) fields, it's returning data very fast.
You are trying to pull 600+Kb out of the database for every record. 20 rows makes that almost 6Mb at a minimum per query.
The reason it runs quickly in SQL Server Management Studio is that it doesn't actually return the full column, it returns only the first X characters, so not all 6+MB is being processed. When you are running through code (dapper in this case) then all 6+MB is being returned.
If you are storing files in the database, you need to stop doing that and store them in the filesystem, and use the database to store the the locations and metadata of the files.
I'm not anti storing of JSON/XML in the database, but it does give very big lumps of data to return sometimes which will take time to return - and more than in SSMS, which typically doesn't return the full information to you.
BUT - when you're returning this much data, it's important to filter. I doubt your application really needs all the fields or all the records for what it's trying to do; if you filter down to what you actually need in your query, you should get a faster result.
Building my own mini CMS back end in EF + SQL Server (Database First). I have a "Contents" table which all entities link too using a Foreign Key.
CREATE TABLE [dbo].[Contents](
[ContentID] [int] IDENTITY(1,1) NOT NULL,
[ContentType] [varchar](100) NOT NULL,
[DateAdded] [datetime] NOT NULL,
[DateUpdated] [datetime] NULL,
[isDeleted] [bit] NOT NULL,
[UserId] [int] NOT NULL
CREATE TABLE [dbo].[Articles](
[ArticleID] [int] IDENTITY(1,1) NOT NULL,
[ContentID] [int] NOT NULL,
[ImageID] [int] NOT NULL,
[ArticleHeadline] [varchar](250) NOT NULL,
[ArticleSummary] [nvarchar](200) NOT NULL,
[ArticleBody] [nvarchar](500) NOT NULL
ALTER TABLE [dbo].[Articles] WITH CHECK ADD CONSTRAINT [FK_Articles_Contents] FOREIGN KEY([ContentID])
REFERENCES [dbo].[Contents] ([ContentID])
In Entity Framework the Entity Content quite rightly thinks that this is a one to many relationship. How do I go about making this one to one? Content can only belong to one other Entity but I keep having to use First() in my code.
<h1>#Model.Content.Articles.First().ArticleHeadline</h1>
#Html.Raw(Model.Content.Articles.First().ArticleBody)
As for database first approach, to have 1-1 association in EF, the dependent ([dbo].[Articles]) must have a primary key that also is the foreign key to the principal([dbo].[Contents]). It will require some DB design change like this:
CREATE TABLE [dbo].[Contents](
[ContentID] [int] NOT NULL PRIMARY KEY,
[ContentType] [VARCHAR](100) NOT NULL
)
CREATE TABLE [dbo].[Articles](
[ContentID] [int] NOT NULL PRIMARY KEY,
[ImageID] [int] NOT NULL,
CONSTRAINT [FK_Contents] FOREIGN KEY ([ContentID]) REFERENCES [dbo].[Contents] ([ContentID]) ON DELETE CASCADE
)
This should answer your question
http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
Look at the fluent configuration
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
// Configure StudentId as PK for StudentAddress
modelBuilder.Entity<StudentAddress>() .HasKey(e => e.StudentId);
// Configure StudentId as FK for StudentAddress
modelBuilder.Entity<StudentAddress>() .HasRequired(ad => ad.Student) .WithOptional(s => s.StudentAddress); }
Replace student address and student with article content and article
For db first mappings you will need to modify your edmx and regenerate your models.
This may help:
http://www.exceptionnotfound.net/entity-framework-for-beginners-creating-a-database-first-model/
I have been working on a project where I have a table with a computed column. When I start sync, it says:
The column "TotalAmount" cannot be modified because it is either a computed column or is the result of a UNION operator
I want to exclude this column from being sync.
I am using C# and Sql Server 2008 R2.
Table Definition:
CREATE TABLE [dbo].[tblFeeDetails](
[RecordId] [bigint] IDENTITY(1,1) NOT NULL,
[SessionId] [int] NOT NULL,
[CourseId] [int] NOT NULL,
[FormNumber] [nvarchar](50) NOT NULL,
[CourseFee] [money] NOT NULL,
[OtherCharges] [money] NOT NULL,
[LateFee] [money] NOT NULL,
[TotalAmount] AS (([CourseFee]+[OtherCharges])+[LateFee]) PERSISTED,
[Status] [bit] NOT NULL
)
You are using SqlSyncAdapterBuilder, correct? Using that, you can specify which columns to track.
am assuming you're using GetDescriptionForTable to retrieve the schema.
you can either, remove the column from the table description Columns collection or you can manually specify which columns you want included in the GetDescriptionForTable...
e.g.,
// Definition for CustomerContact, including the list of columns to include.
Collection columnsToInclude = new Collection();
columnsToInclude.Add("CustomerId");
columnsToInclude.Add("PhoneType");
DbSyncTableDescription customerContactDescription =
SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.CustomerContact", columnsToInclude, serverConn);
This question already has answers here:
How do you effectively model inheritance in a database?
(9 answers)
Closed 7 years ago.
I have this table:
CREATE TABLE [Entree]
(
[RowId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](250) NOT NULL,
[Description] [nvarchar](250) NULL,
[FK_InspirationSource] [int] NOT NULL,
[Type] [int] NOT NULL,
[PriceRangeType] [int] NOT NULL,
[SoldCount] [int] NOT NULL,
[HolidaySpecial] [bit] NULL,
[DiscountApplicable] [bit] NULL,
[DateCreated] [datetime] NULL,
[LastModified] [datetime] NULL,
[Enabled] [tinyint] NOT NULL,
[BirthDate] [smalldatetime] NULL,
[IG_Int1] [int] NULL,
[IG_Int2] [int] NULL,
[IG_Int3] [int] NULL,
[IG_Int4] [int] NULL,
[IG_Int5] [int] NULL,
[IG_Int6] [int] NULL,
[IG_Int7] [int] NULL,
[IG_Int8] [int] NULL
and in C# code, corresponds to a Entree object with the respectable fields. IG_Int s specify bunch of other properties of the entree in cooking process.
Now, we want to have Derived_Entree objects. In the code, DerivedEntree is an Entree too. So DerivedEntree : Entree.
DerivedEntree has more columns. ParentEntreeId (FK to Entree), ExtraProcessingStep.
So for example, an entree would be "Snail Ravioli" and Derived Entree would be "Broiled snail ravioli".
If there were a separate table, it would be
CREATE TABLE [DerivedEntree]
(
[RowId] [int] IDENTITY(1,1) NOT NULL,
[FK_Entree] [int] NOT NULL,
[ExtraProcessingStep] [int] NOT NULL
)
and add FK_DerivedEntree in Entree table.
So whenever a new entree is entered, a row is inserted to the Entree table, and when a new DerivedEntree is entered, it is inserted to both tables. This is to satisfy the requirement that every Entree has to have a unique Id (which will be a RowId in Entree table)
Instead of adding a separate table, another option is to add those two columns (FK_Entree and ExtraProcessingStep) to the Entree tables and store them there.
What is a more standard practice? I thought about adding additional table because of FK_Entree but perhaps having a foreign key to itself is a common practice?
Melissa, this question is not answerable and depends heavily on your desired usage of the system.
Here are your two main design options:
http://en.wikipedia.org/wiki/Snowflake_schema
The snowflake schema is similar to the star schema. However, in the
snowflake schema, dimensions are normalized into multiple related
tables, whereas the star schema's dimensions are denormalized with
each dimension represented by a single table. A complex snowflake
shape emerges when the dimensions of a snowflake schema are elaborate,
having multiple levels of relationships, and the child tables have
multiple parent tables ("forks in the road").
http://en.wikipedia.org/wiki/Star_schema
The star schema separates business process data into facts, which hold
the measurable, quantitative data about a business, and dimensions
which are descriptive attributes related to fact data. Examples of
fact data include sales price, sale quantity, and time, distance,
speed, and weight measurements. Related dimension attribute examples
include product models, product colors, product sizes, geographic
locations, and salesperson names.
A star schema that has many dimensions is sometimes called a centipede
schema.[3] Having dimensions of only a few attributes, while simpler
to maintain, results in queries with many table joins and makes the
star schema less easy to use.