#c# #sql #entity-framework #linq #linq-to-entities
#c# #sql #entity-framework #linq #linq-to-entities
Вопрос:
Я создаю проект редактирования существующего рецепта
Пожалуйста, обратите внимание-— В каждом рецепте может быть более одной группы ингредиентов (- это моя точка зрения при создании этого проекта)
- Таблица рецептов (идентификатор рецепта, имя и т.д.)
- Привязка таблицы группы ингредиентов для каждого рецепта Диаграммы для каждого рецепта (идентификатор группы, название группы пример: (для основы, для соуса))
- Есть таблица ингредиентов (идентификатор и имя)
- Таблица, содержащая список ингредиентов для всех групп ингредиентов ingredientsInChart (идентификатор для каждого ингредиента, ИДЕНТИФИКАТОР, к какой группе ингредиентов он принадлежит, идентификатор ингредиента, количество,)
У кого-нибудь есть идея, как мне получить названия ингредиентов, связанных с одной группой ингредиентов? В C # MVC, конечно, не в SQL
мои вопросы:
как я могу сделать это в одной функции? как правильно это написать, чтобы это работало. если возможно, не копировать и не создавать новые таблицы.
Обратите внимание, что у меня пока нет FK в моих таблицах. В конце мне нужно получить из базы данных группы ингредиентов для каждого рецепта. и все группы ингредиентов находятся в одной таблице и имеют только идентификатор ингредиентов’, идентификатор групп, а не их название.
Я начал писать эти функции :
в контроллере рецептов:
mydata db = new data()
private List<ChartsForOneRecipe> lchart;
-
Функция, которая возвращает все группы, которые принадлежат определенному рецепту, работает хорошо
[HttpGet] public IHttpActionResult GetTheNamesOfChartsByRecipeId(int RecipeId) { lchart = db.ChartsForOneRecipe.Where(ch => ch.recipeId == RecipeId).ToList(); return base.Ok(lchart); }
-
Функция, которая возвращает все ингредиенты в определенной группе ингредиентов, и это не сработало
[HttpGet]//return all ingredients in a chart by getting chartid public IHttpActionResult GetAlltheIngredientsInChart(int ChartId) { var q = from ing in db.Ingredients from ingch in db.IngredientsInChart where (ing.ingredientID == ingch.ingredientsInChartId amp;amp; ingch.chartId == ChartId) select new { ing.ingredientID, ing.name }; return Ok(q);
}
Комментарии:
1. «В C # MVC, конечно, не в SQL» … на самом деле вы имеете в виду «в entity Framework», я думаю. Вы все еще пытаетесь получить информацию из базы данных. Код C # linq / EF преобразуется в SQL под поверхностью. Это Entity Framework, который фактически выполняет эту задачу. Вы можете сделать это в любой .NET-программе, а не только в MVC. Я изменил ваши теги, чтобы они были немного более актуальными (что, надеюсь, поможет задать ваш вопрос нужной аудитории).
2. Запрос не возвращает результатов или выдает исключение? Если вы не получаете никаких результатов, удалите WHERE и посмотрите, какие результаты вы получаете. Для тестирования я бы добавил к результатам значения ingch, чтобы вы могли определить основную причину.
Ответ №1:
при условии, что у вас есть свойство навигации Ingredient, установленное в IngredientsInChart, следующий запрос будет работать
var q = db.IngredientsInChart.Where(inc => inc.chartId == ChartId)
.Include(inc => inc.Ingredient)
.Select(inc => new {
inc.ingredientsInChartId,
inc.Ingredient.name
}).ToList();
Ответ №2:
Учитывая, что вы сначала используете код EF6, и вы определили свои модели с их соответствующими аннотациями данных для настройки ваших ключей, следующим образом:
public class Ingredients
{
[Key]
public int IngredientId { get; set; }
public string Name { get; set; }
//Begin Other irrelevant attributes
//...
//End irrelevant attributes
//Navigation property - THIS IS IMPORTANT
[ForeignKey("IngredientsInChartId")]
public ICollection<IngredientsInChart> IngredientsInChart { get; set; }
}
public class IngredientsInChart
{
[Key]
public int ChartId { get; set; }
public string Name { get; set; }
//Begin Other irrelevant attributes
//...
//End irrelevant attributes
//Optional, on using FLUENT-API for seeding data (Migration)
public int IngredientsInChartId { get; set; }
//Navigation property - THIS IS IMPORTANT
[ForeignKey("IngredientsInChartId")]
public Ingredients Ingredient { get; set; }
}
Или вы можете использовать FluentAPI, настроив свой контекст следующим образом:
public class MyData : DbContext
{
public virtual DbSet<ChartsForOneRecipe> ChartsForOneRecipe { get; set; }
public virtual DbSet<Recipe> Recipe { get; set; }
//Other irrelevant DBSet properties
public MyData(DbContextOptions<PharmaDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Primary keys
modelBuilder.Entity<Ingredients>()
.Property(c => c.IngredientId)
.UseIdentityAlwaysColumn();
modelBuilder.Entity<IngredientsInChart>()
.Property(c => c.ChartId)
.UseIdentityAlwaysColumn();
//Foreign keys
modelBuilder.Entity<Ingredients>()
.HasMany(c => c.IngredientsInChart)
.WithOne(k => k.Ingredient)
.HasForeignKey(fk => fk.IngredientsInChartId);
modelBuilder.Entity<IngredientsInChart>()
.HasOne(k => k.Ingredient)
.WithMany(c => c.IngredientsInChart)
.HasForeignKey(fk => fk.IngredientsInChartId);
}
}
И, наконец, мы могли бы загрузить данные следующим образом:
Быстрая загрузка
Используя подход с быстрой загрузкой, мы должны загрузить все ингредиенты перед загрузкой связанных ингредиентов в диаграмму:
[HttpGet]//return all ingredients in a chart by getting chartid
public IHttpActionResult GetAlltheIngredientsInChart(int ChartId)
{
var ingredients = db.Ingredients.ToList();
var q = db.IngredientsInChart.Where(ingch => ingch.Id == ChartId)
.Include(ingch => ingch.Ingredient)
.Select(ingch => new { ingch.IngredientsInChartId, ingch.Ingredient.Name })
.ToList();
return Ok(q);
}
Отложенная загрузка
Вам не нужно загружать ингредиенты (удалить var ingredients = db.Ingredients.ToList();
и Include(ingch => ingch.Ingredient)
). Однако вам может потребоваться установить пакет Nuget EF Proxy и выполнить настройку в вашем стартовом проекте следующим образом:
public void ConfigureServices(IServiceCollection services)
{
#region Database configuration
// Database configuration
services.AddDbContext<MyData>(options =>
options.UseLazyLoadingProxies()
.UseSqlServer(Configuration.GetConnectionString("MyConnectionString")));
#endregion Database configuration
}
Для дальнейшего чтения я настоятельно рекомендую прочитать: